forked from oreillymedia/Learning-OpenCV-3_examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Exercises_9_1-2-10-11-12-15-16.cpp
221 lines (215 loc) · 9.86 KB
/
Exercises_9_1-2-10-11-12-15-16.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
//Exercises_9_1-2-10-11-12-15-16.cpp Exercises at end of Chapter 8
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void help(const char **argv) {
cout << "\n\n"
<< "This program solves the Exercise 1、2、10、11、12、15 and 16 at the end of Chapter 9 \n"
<< "Call:\n"
<< argv[0] << " <path/image_name>\n\n"
<< "For example: ./" << argv[0] << " ../lena.jpg\n"
<< endl;
}
int main( int argc, const char** argv )
{
help(argv);
if(argc < 2) {
cout << "\nERROR: You had too few parameters.\n" << endl;
return -1;
}
Mat src ;
Mat gray;
Mat mask;
Mat temp;
Mat temp2;
/************************************************************************/
/* 1. Load an image with interesting textures. Smooth the image in several ways using
cv::smooth() with smoothtype=cv::GAUSSIAN.
a. Use a symmetric 3 × 3, 5 × 5, 9 × 9, and 11 × 11 smoothing window size and
display the results.
b. Are the output results nearly the same by smoothing the image twice with a
5 × 5 Gaussian filter as when you smooth once with two 11 × 11 filters? Why
or why not? */
/************************************************************************/
src = imread(argv[1]);
if (src.empty())
{
cout << "\nERROR: parameters is not a image name.\n" << endl;
return -1;
}
double minPixelValue, maxPixelValue;
//a
Mat smooth33;Mat smooth55;Mat smooth99;Mat smooth111;
GaussianBlur(src,smooth33,cv::Size(3,3),0);
GaussianBlur(src,smooth55,cv::Size(5,5),0);
GaussianBlur(src,smooth99,cv::Size(9,9),0);
GaussianBlur(src,smooth111,cv::Size(11,11),0);
//b
GaussianBlur(smooth55,smooth55,cv::Size(5,5),0);
temp = smooth55 - smooth111;
cv::minMaxIdx(temp, &minPixelValue, &maxPixelValue);
// maxPixelVaule = 19 ,the result is " 5 × 5 Gaussian filter twice" is much like "11 × 11 filters"
/************************************************************************/
/* 2. Create a 100 × 100 single-channel image. Set all pixels to 0. Finally, set the center
pixel equal to 255.
a. Smooth this image with a 5 × 5 Gaussian filter and display the results. What
did you find?
b. Do this again but with a 9 × 9 Gaussian filter.
c. What does it look like if you start over and smooth the image twice with the 5
× 5 filter? Compare this with the 9 × 9 results. Are they nearly the same? Why
or why not?
*/
/************************************************************************/
Mat singleChanel100 = Mat(100,100,CV_8U,Scalar(0));
singleChanel100.at<uchar>(50,50) = 255;
//a
GaussianBlur(singleChanel100,temp,cv::Size(5,5),0);
imshow("5 × 5 Gaussian filter",temp);
//b
GaussianBlur(singleChanel100,temp,cv::Size(9,9),0);
imshow("9 × 9Gaussian filter",temp);
//c
GaussianBlur(singleChanel100,temp,cv::Size(5,5),0);
GaussianBlur(temp,temp,cv::Size(5,5),0);
GaussianBlur(singleChanel100,temp2,cv::Size(9,9),0);
absdiff(temp,temp2,temp2);
cv::minMaxIdx(temp2, &minPixelValue, &maxPixelValue);
//maxPixelVaule = 5,the result are nearly the same
/************************************************************************/
/* 10. Create a low-variance random image (use a random number call such that the
numbers don’t differ by much more than three and most numbers are near zero).
Load the image into a drawing program such as PowerPoint, and then draw a
wheel of lines meeting at a single point. Use bilateral filtering on the resulting
image and explain the results. */
/************************************************************************/
Mat matLowVariance = Mat(512,512,CV_8U,Scalar(0));
RNG arng = cv::theRNG();
arng.fill(matLowVariance,RNG::UNIFORM,0,30);
//draw a wheel of lines meeting at the center
line(matLowVariance,Point(256,256),Point(256,256-100),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256+100,256+100),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256+100,256),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256+100,256-100),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256,256+100),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256-100,256-100),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256-100,256),Scalar(255),1);
line(matLowVariance,Point(256,256),Point(256-100,256+100),Scalar(255),1);
imshow("a wheel of lines meeting at a single point",matLowVariance);
bilateralFilter(matLowVariance,temp,5,10.0,2.0);
imshow("bilateralFilter",temp);
/************************************************************************/
/* 11. Load an image of a scene and convert it to grayscale.
a. Run the morphological Top Hat operation on your image and display theresults.
b. Convert the resulting image into an 8-bit mask.
c. Copy a grayscale value into the original image where the Top Hat mask (from
Part b of this exercise) is nonzero. Display the results. */
/************************************************************************/
cvtColor(src,gray,COLOR_BGR2GRAY);
//a
morphologyEx(gray,temp,CV_MOP_TOPHAT,Mat());
imshow(" morphological Top Hat",temp);
//b
temp.convertTo(mask,CV_8UC1);
//c
cvtColor(gray,gray,COLOR_GRAY2BGR);
gray.copyTo(src,mask);
imshow("execrise 11 result",src);
/************************************************************************/
/* 12. Load an image with many details.
a. Use resize() to reduce the image by a factor of 2 in each dimension (hence
the image will be reduced by a factor of 4). Do this three times and display the
results.
b. Now take the original image and use cv::pyrDown() to reduce it three times,
and then display the results.
c. How are the two results different? Why are the approaches different?
*/
/************************************************************************/
//a
Mat matResize;
resize(src,matResize,cv::Size(0,0),0.5,0.5);
resize(matResize,matResize,cv::Size(0,0),0.5,0.5);
resize(matResize,matResize,cv::Size(0,0),0.5,0.5);
imshow("resize 3 times",matResize);
//b
Mat matPyrDown;
pyrDown(src,matPyrDown);
pyrDown(matPyrDown,matPyrDown);
pyrDown(matPyrDown,matPyrDown);
imshow("pyrDown 3 times",matPyrDown);
//c
absdiff(matResize,matPyrDown,temp);
imshow("two results of resize and pyDown diff",temp);
/************************************************************************/
/* 15. Use cv::filter2D() to create a filter that detects only 60-degree lines in an
image. Display the results on a sufficiently interesting image scene. */
/************************************************************************/
Mat matWithLines = Mat(512,512,CV_8UC1,Scalar(0));
// create 9 lines
for (int i=0;i<9;i++)
{
line(matWithLines,Point(arng.uniform(0,512),arng.uniform(0,521)),Point(arng.uniform(0,512),arng.uniform(0,521)),Scalar(255),1);
}
//45 degree line
line(matWithLines,Point(0,512),Point(512,0),Scalar(255),1);
matWithLines.convertTo(matWithLines,CV_32FC1,1.0/255);
// detects only 45-degree lines
Mat matKernel = Mat(3,3,CV_32FC1,Scalar(0));
matKernel.at<float>(0,0) = 0 ;
matKernel.at<float>(0,1) = 0 ;
matKernel.at<float>(0,2) = 1.0/3 ;
matKernel.at<float>(1,0) = 0 ;
matKernel.at<float>(1,1) = 1.0/3 ;
matKernel.at<float>(1,2) = 0 ;
matKernel.at<float>(2,0) = 1.0/3 ;
matKernel.at<float>(2,1) = 0;
matKernel.at<float>(2,2) = 0;
filter2D(matWithLines,temp,CV_32FC1,matKernel);
threshold(temp,temp,0.99,1,CV_THRESH_BINARY);
/************************************************************************/
/* 16. Separable kernels: create a 3 × 3 Gaussian kernel using rows [(1/16, 2/16, 1/16),
(2/16, 4/16, 2/16), (1/16, 2/16, 1/16)] and with anchor point in the middle.
a. Run this kernel on an image and display the results.
b. Now create two one-dimensional kernels with anchors in the center: one
going “across” (1/4, 2/4, 1/4), and one going down (1/4, 2/4, 1/4). Load the
same original image and use cv::filter2D() to convolve the image twice,
once with the first 1D kernel and once with the second 1D kernel. Describe
the results.
c. Describe the order of complexity (number of operations) for the kernel in
part a and for the kernels in part b. The difference is the advantage of being
able to use separable kernels and the entire Gaussian class of filters—or any
linearly decomposable filter that is separable, since convolution is a linear
operation. */
/************************************************************************/
Mat matGaussianKernel = Mat(3,3,CV_32FC1,Scalar(0));
matGaussianKernel.at<float>(0,0) = 1.0/16;
matGaussianKernel.at<float>(0,1) = 2.0/16;
matGaussianKernel.at<float>(0,2) = 1.0/16;
matGaussianKernel.at<float>(1,0) = 2.0/16;
matGaussianKernel.at<float>(1,1) = 4.0/16;
matGaussianKernel.at<float>(1,2) = 2.0/16;
matGaussianKernel.at<float>(2,0) = 1.0/16;
matGaussianKernel.at<float>(2,1) = 2.0/16;
matGaussianKernel.at<float>(2,2) = 1.0/16;
//a
src.convertTo(temp,CV_32F,1.0/255);
filter2D(temp,temp,CV_32F,matGaussianKernel);
imshow("a 3 × 3 Gaussian kernel",temp);
//b
Mat matKernel1 = Mat(1,3,CV_32FC1,Scalar(0));
Mat matKernel2 = Mat(3,1,CV_32FC1,Scalar(0));
matKernel1.at<float>(0,0) = 1.0/4;
matKernel1.at<float>(0,1) = 2.0/4;
matKernel1.at<float>(0,2) = 1.0/4;
matKernel2.at<float>(0,0) = 1.0/4;
matKernel2.at<float>(1,0) = 2.0/4;
matKernel2.at<float>(2,0) = 1.0/4;
filter2D(temp,temp2,CV_32F,matKernel1);
filter2D(temp2,temp2,CV_32F,matKernel2);
absdiff(temp,temp2,temp2);
//temp and temp2 is just the same mat,maxPixelValue is very small,nearly ZERO
cv::minMaxIdx(temp2, &minPixelValue, &maxPixelValue);
//c the order is no matter
waitKey();
return 0;
}