-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsobel.cpp
146 lines (122 loc) · 3.39 KB
/
sobel.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
// header inclusion
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
void convolve(
cv::Mat &input,
cv::Mat kernel,
cv::Mat &blurredOutput);
void getMag (
cv::Mat dx,
cv::Mat dy,
cv::Mat &output);
void getDir (
cv::Mat dx,
cv::Mat dy,
cv::Mat &output);
void normalizeMat (
cv::Mat &in,
double factor);
int main( int argc, char** argv )
{
// LOADING THE IMAGE
char* imageName = argv[1];
char* dxOutputName = argv[2];
char* dyOutputName = argv[3];
char* magOutputName = argv[4];
char* dirOutputName = argv[5];
Mat image;
image = imread( imageName, CV_LOAD_IMAGE_GRAYSCALE );
// CONVERT COLOUR, BLUR AND SAVE
Mat _64fimage;
image.convertTo(_64fimage, CV_64F);
Mat dxkernel = (Mat_<int>(3,3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
Mat dykernel = (Mat_<int>(3,3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
Mat dx;
Mat dy;
Mat mag;
Mat dir;
convolve(_64fimage, dxkernel, dx);
convolve(_64fimage, dykernel, dy);
getMag (dx, dy, mag);
getDir (dx, dy, dir);
normalizeMat (dx, 128.0);
normalizeMat (dy, 128.0);
normalizeMat (dir, CV_PI/2);
dir = dir*(255/CV_PI);
imwrite( dxOutputName, dx);
imwrite( dyOutputName, dy);
imwrite( magOutputName, mag);
imwrite( dirOutputName, dir);
return 0;
}
void convolve(cv::Mat &input, cv::Mat kernel, cv::Mat &output)
{
// intialise the output using the input
output.create(input.size(), CV_64F);
// we need to create a padded version of the input
// or there will be border effects
int kernelRadiusX = ( kernel.size[0] - 1 ) / 2;
int kernelRadiusY = ( kernel.size[1] - 1 ) / 2;
cv::Mat paddedInput;
cv::copyMakeBorder( input, paddedInput,
kernelRadiusX, kernelRadiusX, kernelRadiusY, kernelRadiusY,
cv::BORDER_REPLICATE );
// now we can do the convoltion
for ( int i = 0; i < input.rows; i++ )
{
for( int j = 0; j < input.cols; j++ )
{
double sum = 0.0;
for( int m = -kernelRadiusX; m <= kernelRadiusX; m++ )
{
for( int n = -kernelRadiusY; n <= kernelRadiusY; n++ )
{
// find the correct indices we are using
int imagex = i + m + kernelRadiusX;
int imagey = j + n + kernelRadiusY;
int kernelx = m + kernelRadiusX;
int kernely = n + kernelRadiusY;
// get the values from the padded image and the kernel
double imageval = ( double ) paddedInput.at<double>( imagex, imagey );
int kernalval = kernel.at<int>( kernelx, kernely );
// do the multiplication
sum += imageval * kernalval;
}
}
// set the output value as the sum of the convolution
output.at<double>(i, j) = (double) sum;
}
}
}
void getDir(cv::Mat dx, cv::Mat dy, cv::Mat &output) {
output.create(dx.size(), dx.type());
for ( int i = 0; i < dx.rows; i++ )
{
for( int j = 0; j < dy.cols; j++ )
{
if (dy.at<double>(i,j) != 0 && dx.at<double>(i,j) != 0) {
output.at<double>(i,j) = atan2 (dy.at<double>(i,j), dx.at<double>(i,j));
} else {
output.at<double>(i,j) = (double) atan (0);
}
}
}
}
void getMag (cv::Mat dx, cv::Mat dy, cv::Mat &output) {
output.create(dx.size(), dx.type());
for ( int i = 0; i < dx.rows; i++ )
{
for( int j = 0; j < dy.cols; j++ )
{
output.at<double>(i,j) = sqrt ((dx.at<double> (i,j) * dx.at<double> (i,j)) + (dy.at<double>(i,j) * dy.at<double>(i,j)));
}
}
}
void normalizeMat (cv::Mat &in, double factor) {
for (int i=0;i<in.rows;i++) {
for (int j=0;j<in.cols;j++) {
in.at<double>(i,j) = (double) in.at<double>(i,j)/2 + factor;
}
}
}