-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathcanny.cp
178 lines (127 loc) · 5.49 KB
/
canny.cp
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
/*
* canny.cpp
*
* Author: Angelo Gonzalez
*/
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void followEdges(int x, int y, Mat &magnitude, int tUpper, int tLower, Mat &edges) {
edges.at<float>(y, x) = 255;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
//make sure we don't go out of bounds and check that we do not look at the same pixel twice
if((i != 0) && (j != 0) && (x + i >= 0) && (y + j >= 0) && (x + i <= magnitude.cols) && (y + j <= magnitude.rows)){
if((magnitude.at<float>(y + j, x + i) > tLower) && (edges.at<float>(y + j, x + i) != 255)) {
followEdges(x + i, y + j, magnitude, tUpper, tLower, edges);
}
}
}
}
}
void edgeDetect(Mat &magnitude, int tUpper, int tLower, Mat &edges) {
int rows = magnitude.rows;
int cols = magnitude.cols;
edges = Mat(magnitude.size(), CV_32F, 0.0);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
if (magnitude.at<float>(y, x) >= tUpper){
followEdges(x, y, magnitude, tUpper, tLower, edges);
}
}
}
}
void nonMaximumSuppression(Mat &magnitudeImage, Mat &directionImage) {
//used to mirror positions in magnitude Mat
Mat checkImage = Mat(magnitudeImage.rows, magnitudeImage.cols, CV_8U);
//using MatIterator to iterate through the Mats
MatIterator_<float>itMag = magnitudeImage.begin<float>();
MatIterator_<float>itDirection = directionImage.begin<float>();
MatIterator_<unsigned char>itRet = checkImage.begin<unsigned char>();
MatIterator_<float>itEnd = magnitudeImage.end<float>();
//Calculates the direction in this loop
for (; itMag != itEnd; ++itDirection, ++itRet, ++itMag) {
const Point pos = itRet.pos();
float currentDirection = atan(*itDirection) * (180 / 3.142);
while(currentDirection < 0) currentDirection += 180;
*itDirection = currentDirection;
//checks to make sure we don't go out of bounds
if (currentDirection > 22.5 && currentDirection <= 67.5) {
if(pos.y > 0 && pos.x > 0 && *itMag <= magnitudeImage.at<float>(pos.y - 1, pos.x - 1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
if(pos.y < magnitudeImage.rows-1 && pos.x < magnitudeImage.cols-1 && *itMag <= magnitudeImage.at<float>(pos.y + 1, pos.x + 1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
}
else if(currentDirection > 67.5 && currentDirection <= 112.5) {
if(pos.y > 0 && *itMag <= magnitudeImage.at<float>(pos.y-1, pos.x)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
if(pos.y<magnitudeImage.rows-1 && *itMag<=magnitudeImage.at<float>(pos.y+1, pos.x)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
}
else if(currentDirection > 112.5 && currentDirection <= 157.5) {
if(pos.y>0 && pos.x<magnitudeImage.cols-1 && *itMag<=magnitudeImage.at<float>(pos.y-1, pos.x+1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;;
}
if(pos.y < magnitudeImage.rows-1 && pos.x>0 && *itMag<=magnitudeImage.at<float>(pos.y+1, pos.x-1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
}
else {
if(pos.x > 0 && *itMag <= magnitudeImage.at<float>(pos.y, pos.x-1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
if(pos.x < magnitudeImage.cols-1 && *itMag <= magnitudeImage.at<float>(pos.y, pos.x+1)) {
magnitudeImage.at<float>(pos.y, pos.x) = 0;
}
}
}
}
void MyCanny(Mat &src, Mat &edges, int upperThresh, int lowerThresh) {
Mat image = src.clone();;
//convert to grayscale
//cvtColor(src, image, CV_BGR2GRAY);
//Noise reduction
GaussianBlur(src, image, Size(3, 3), 1.5);
//calculate magnitudes and direction using Sobel
Mat magX = Mat(src.rows, src.cols, CV_32F);
Mat magY = Mat(src.rows, src.cols, CV_32F);
Sobel(image, magX, CV_32F, 1, 0, 3);
Sobel(image, magY, CV_32F, 0, 1, 3);
//calculate slope
Mat slopes = Mat(image.rows, image.cols, CV_32F); //directions are calculated in the nonMaximumSuppression method
divide(magY, magX, slopes);
//caclulate magnitude of the gradient at each pixel
Mat sum = Mat(image.rows, image.cols, CV_64F);
Mat prodX = Mat(image.rows, image.cols, CV_64F);
Mat prodY = Mat(image.rows, image.cols, CV_64F);
multiply(magX, magX, prodX);
multiply(magY, magY, prodY);
sum = prodX + prodY;
sqrt(sum, sum);
Mat magnitude = sum.clone();
//Non Maximum Suppression
nonMaximumSuppression(magnitude, slopes);
//edge detection and following
edgeDetect(magnitude, upperThresh, lowerThresh, edges);
}
int main(int argc, const char * argv[])
{
Mat input;
input = imread(argv[1], 0); //reads as greyscale
int tUpper = atoi(argv[2]);
int tLower = atoi(argv[3]);
Mat edges;
MyCanny(input, edges, tUpper, tLower);
string s1 = "edge";
string s2 = argv[1];
string outName = s1 + s2;
imshow("original", input);
imshow(outName, edges);
waitKey();
return 0;
}