问题描述
我的任务是制作自己的 Sobel 方法,而不是使用 OpenCV 中的 cv::Sobel
.我尝试实现我在 编程技术
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
当我运行程序时,cv::Mat
会抛出一个错误.有人知道为什么吗?
When I run the program, cv::Mat
throws an error, however. Anyone have any idea why?
索贝尔方法:
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);
}
主要内容:
int main(int argc, char* argv[]) {
Mat image;
imageOutput(image, "C:/Dropbox/2-falling-toast-ted-kinsman.jpg");
return 0;
}
absVal 方法:
int absVal(int v)
{
return v*((v < 0)*(-1) + (v > 0));
}
运行时抛出此错误:
Unhandled exception at 0x00007FFC9365A1C8 in Miniproject01.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000A780A4F110.
并指向此处:
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!
推荐答案
此代码片段用于演示如何计算 Sobel 3x3 导数,将图像与 Sobel 核进行卷积.您可以轻松扩展到不同的内核大小,将内核半径作为 my_sobel
的输入,并创建适当的内核.
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.
#include <opencv2opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
void my_sobel(const Mat1b& src, Mat1s& dst, int direction)
{
Mat1s kernel;
int radius = 0;
// Create the kernel
if (direction == 0)
{
// Sobel 3x3 X kernel
kernel = (Mat1s(3,3) << -1, 0, +1, -2, 0, +2, -1, 0, +1);
radius = 1;
}
else
{
// Sobel 3x3 Y kernel
kernel = (Mat1s(3, 3) << -1, -2, -1, 0, 0, 0, +1, +2, +1);
radius = 1;
}
// Handle border issues
Mat1b _src;
copyMakeBorder(src, _src, radius, radius, radius, radius, BORDER_REFLECT101);
// Create output matrix
dst.create(src.rows, src.cols);
// Convolution loop
// Iterate on image
for (int r = radius; r < _src.rows - radius; ++r)
{
for (int c = radius; c < _src.cols - radius; ++c)
{
short s = 0;
// Iterate on kernel
for (int i = -radius; i <= radius; ++i)
{
for (int j = -radius; j <= radius; ++j)
{
s += _src(r + i, c + j) * kernel(i + radius, j + radius);
}
}
dst(r - radius, c - radius) = s;
}
}
}
int main(void)
{
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Compute custom Sobel 3x3 derivatives
Mat1s sx, sy;
my_sobel(img, sx, 0);
my_sobel(img, sy, 1);
// Edges L1 norm
Mat1b edges_L1;
absdiff(sx, sy, edges_L1);
// Check results against OpenCV
Mat1s cvsx,cvsy;
Sobel(img, cvsx, CV_16S, 1, 0);
Sobel(img, cvsy, CV_16S, 0, 1);
Mat1b cvedges_L1;
absdiff(cvsx, cvsy, cvedges_L1);
Mat diff_L1;
absdiff(edges_L1, cvedges_L1, diff_L1);
cout << "Number of different pixels: " << countNonZero(diff_L1) << endl;
return 0;
}
这篇关于OpenCV 中的 Sobel 导数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!