I have been tasked with making my own Sobel method, and not use the cv::Sobel found in OpenCV. I tried implementing one I found at Programming techniques
When I run the program, cv::Mat throws an error, however. Anyone have any idea why?
Sobel method:
int sobelCorrelation(Mat InputArray, int x, int y, String xory)
{
if (xory == "x") {
return InputArray.at<uchar>(y - 1, x - 1) +
2 * InputArray.at<uchar>(y, x - 1) +
InputArray.at<uchar>(y + 1, x - 1) -
InputArray.at<uchar>(y - 1, x + 1) -
2 * InputArray.at<uchar>(y, x + 1) -
InputArray.at<uchar>(y + 1, x + 1);
}
else if (xory == "y")
{
return InputArray.at<uchar>(y - 1, x - 1) +
2 * InputArray.at<uchar>(y - 1, x) +
InputArray.at<uchar>(y - 1, x + 1) -
InputArray.at<uchar>(y + 1, x - 1) -
2 * InputArray.at<uchar>(y + 1, x) -
InputArray.at<uchar>(y + 1, x + 1);
}
else
{
return 0;
}
}
Calling and processing it in another function:
void imageOutput(Mat image, String path) {
image = imread(path, 0);
Mat dst;
dst = image.clone();
int sum, gx, gy;
if (image.data && !image.empty()){
for (int y = 0; y < image.rows; y++)
for (int x = 0; x < image.cols; x++)
dst.at<uchar>(y, x) = 0.0;
for (int y = 1; y < image.rows - 1; ++y) {
for (int x = 1; x < image.cols - 1; ++x){
gx = sobelCorrelation(image, x, y, "x");
gy = sobelCorrelation(image, x, y, "y");
sum = absVal(gx) + absVal(gy);
if (sum > 255)
sum = 255;
else if (sum < 0)
sum = 0;
dst.at<uchar>(x, y) = sum;
}
}
namedWindow("Original");
imshow("Original", image);
namedWindow("Diagonal Edges");
imshow("Diagonal Edges", dst);
}
waitKey(0);
}
Main:
int main(int argc, char* argv[]) {
Mat image;
imageOutput(image, "C:/Dropbox/2-falling-toast-ted-kinsman.jpg");
return 0;
}
The absVal method:
int absVal(int v)
{
return v*((v < 0)*(-1) + (v > 0));
}
When run it throws this error: "Unhandled exception at 0x00007FFC9365A1C8 in Miniproject01.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000A780A4F110." and points to here:
template<typename _Tp> inline
_Tp& Mat::at(int i0, int i1)
{
CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
(unsigned)(i1 * DataType<_Tp>::channels) < (unsigned)(size.p[1] * channels()) &&
CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
return ((_Tp*)(data + step.p[0] * i0))[i1];
}
If anyone have any advice or ideas what I am doing wrong it would be greatly appreciated!
thanks for the post, I was able to generate gradiant map using the above kernel, and using openCV code filter2D getting from Using custom kernel in opencv 2DFilter - causing crash ... convolution how?
to convolve the image with the kernel. the code that I used is
This code snippet is to demonstrate how to compute Sobel 3x3 derivatives convolving the image with Sobel kernels. You can easily extend to different kernel sizes giving the kernel radius as input to
my_sobel
, and creating the appropriate kernel.If i were you, i would almost always avoid using for loops(if possible). Unnecessary for loops tend to slow down the execution. Instead, reuse wherever possible. For example, the code below uses filter2D give 2d Correlation result:
If you would like to get convolution results, you would need to flip the kernel 'kern' before filtering.
If you would like to squeeze more performance, you can use separable filters 'sepFilter2D'.