Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | /*------------------------------------------------------------------------------------------*\ |
2 | This file contains material supporting chapter 6 of the cookbook: |
||
3 | Computer Vision Programming using the OpenCV Library. |
||
4 | by Robert Laganiere, Packt Publishing, 2011. |
||
5 | |||
6 | This program is free software; permission is hereby granted to use, copy, modify, |
||
7 | and distribute this source code, or portions thereof, for any purpose, without fee, |
||
8 | subject to the restriction that the copyright notice may not be removed |
||
9 | or altered from any source or altered source distribution. |
||
10 | The software is released on an as-is basis and without any warranties of any kind. |
||
11 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. |
||
12 | The author disclaims all warranties with regard to this software, any use, |
||
13 | and any consequent failure, is purely the responsibility of the user. |
||
14 | |||
15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name |
||
16 | \*------------------------------------------------------------------------------------------*/ |
||
17 | |||
18 | #if !defined LAPLACEZC |
||
19 | #define LAPLACEZC |
||
20 | |||
21 | #include <opencv2/core/core.hpp> |
||
22 | #include <opencv2/imgproc/imgproc.hpp> |
||
23 | |||
24 | class LaplacianZC { |
||
25 | |||
26 | private: |
||
27 | |||
28 | // original image |
||
29 | cv::Mat img; |
||
30 | |||
31 | // 32-bit float image containing the Laplacian |
||
32 | cv::Mat laplace; |
||
33 | // Aperture size of the laplacian kernel |
||
34 | int aperture; |
||
35 | |||
36 | public: |
||
37 | |||
38 | LaplacianZC() : aperture(3) {} |
||
39 | |||
40 | // Set the aperture size of the kernel |
||
41 | void setAperture(int a) { |
||
42 | |||
43 | aperture= a; |
||
44 | } |
||
45 | |||
46 | // Get the aperture size of the kernel |
||
47 | int getAperture() const { |
||
48 | |||
49 | return aperture; |
||
50 | } |
||
51 | |||
52 | // Compute the floating point Laplacian |
||
53 | cv::Mat computeLaplacian(const cv::Mat& image) { |
||
54 | |||
55 | |||
56 | // Compute Laplacian |
||
57 | cv::Laplacian(image,laplace,CV_32F,aperture); |
||
58 | |||
59 | // Keep local copy of the image |
||
60 | // (used for zero-crossings) |
||
61 | img= image.clone(); |
||
62 | |||
63 | return laplace; |
||
64 | } |
||
65 | |||
66 | // Get the Laplacian result in 8-bit image |
||
67 | // zero corresponds to gray level 128 |
||
68 | // if no scale is provided, then the max value will be |
||
69 | // scaled to intensity 255 |
||
70 | // You must call computeLaplacian before calling this method |
||
71 | cv::Mat getLaplacianImage(double scale=-1.0) { |
||
72 | |||
73 | if (scale<0) { |
||
74 | |||
75 | double lapmin, lapmax; |
||
76 | cv::minMaxLoc(laplace,&lapmin,&lapmax); |
||
77 | |||
78 | scale= 127/ std::max(-lapmin,lapmax); |
||
79 | } |
||
80 | |||
81 | cv::Mat laplaceImage; |
||
82 | laplace.convertTo(laplaceImage,CV_8U,scale,128); |
||
83 | |||
84 | return laplaceImage; |
||
85 | } |
||
86 | |||
87 | // Get a binary image of the zero-crossings |
||
88 | // if the product of the two adjascent pixels is |
||
89 | // less than threshold then this zero-crossing will be ignored |
||
90 | cv::Mat getZeroCrossings(float threshold=1.0) { |
||
91 | |||
92 | // Create the iterators |
||
93 | cv::Mat_<float>::const_iterator it= laplace.begin<float>()+laplace.step1(); |
||
94 | cv::Mat_<float>::const_iterator itend= laplace.end<float>(); |
||
95 | cv::Mat_<float>::const_iterator itup= laplace.begin<float>(); |
||
96 | |||
97 | // Binary image initialize to white |
||
98 | cv::Mat binary(laplace.size(),CV_8U,cv::Scalar(255)); |
||
99 | cv::Mat_<uchar>::iterator itout= binary.begin<uchar>()+binary.step1(); |
||
100 | |||
101 | // negate the input threshold value |
||
102 | threshold *= -1.0; |
||
103 | |||
104 | for ( ; it!= itend; ++it, ++itup, ++itout) { |
||
105 | |||
106 | // if the product of two adjascent pixel is negative |
||
107 | // then there is a sign change |
||
108 | if (*it * *(it-1) < threshold) |
||
109 | *itout= 0; // horizontal zero-crossing |
||
110 | else if (*it * *itup < threshold) |
||
111 | *itout= 0; // vertical zero-crossing |
||
112 | } |
||
113 | |||
114 | return binary; |
||
115 | } |
||
116 | |||
117 | // Get a binary image of the zero-crossings |
||
118 | // if the product of the two adjacent pixels is |
||
119 | // less than threshold then this zero-crossing will be ignored |
||
120 | cv::Mat getZeroCrossingsWithSobel(float threshold) { |
||
121 | |||
122 | cv::Mat sx; |
||
123 | cv::Sobel(img,sx,CV_32F,1,0,1); |
||
124 | cv::Mat sy; |
||
125 | cv::Sobel(img,sy,CV_32F,0,1,1); |
||
126 | |||
127 | // Create the iterators |
||
128 | cv::Mat_<float>::const_iterator it= laplace.begin<float>()+laplace.step1(); |
||
129 | cv::Mat_<float>::const_iterator itend= laplace.end<float>(); |
||
130 | cv::Mat_<float>::const_iterator itup= laplace.begin<float>(); |
||
131 | cv::Mat_<float>::const_iterator itx= sx.begin<float>()+sx.step1(); |
||
132 | cv::Mat_<float>::const_iterator ity= sy.begin<float>()+sy.step1(); |
||
133 | |||
134 | // Binary image initialize to white |
||
135 | cv::Mat binary(laplace.size(),CV_8U,cv::Scalar(255)); |
||
136 | cv::Mat_<uchar>::iterator itout= binary.begin<uchar>()+binary.step1(); |
||
137 | |||
138 | for ( ; it!= itend; ++it, ++itup, ++itout, ++itx, ++ity) { |
||
139 | |||
140 | // if the product of two adjacent pixel is negative |
||
141 | // then there is a sign change |
||
142 | if (*it * *(it-1) < 0.0 && fabs(*ity) > threshold) |
||
143 | *itout= 0; // horizontal zero-crossing |
||
144 | else if (*it * *itup < 0.0 && fabs(*ity) > threshold) |
||
145 | *itout= 0; // vertical zero-crossing |
||
146 | } |
||
147 | |||
148 | return binary; |
||
149 | } |
||
150 | |||
151 | }; |
||
152 | |||
153 | |||
154 | #endif |