gpt4 book ai didi

c++ - 需要帮助实现特殊的边缘检测器

转载 作者:可可西里 更新时间:2023-11-01 18:38:49 25 4
gpt4 key购买 nike

我正在实现研究论文中的一种方法。该方法的一部分需要一个主要的边缘检测器,作者描述如下:

  1. 获得 DC 图像(对宽度和高度有效地进行 8 倍下采样)
  2. 计算DC图像的Sobel梯度
  3. Threshold Sobel梯度图像(使用T=120)
  4. 清理边缘图像的形态学操作

请注意,这不是 Canny 边缘检测——它们不会为非最大抑制等事情烦恼。我当然可以用 Canny 边缘检测来做到这一点,但我想实现与论文中表达的完全一致。

最后一步是我有点卡住了。

这正是作者所说的:

After obtaining the binary edge map from the edge detection process, a binary morphological operation is employed to remove isolated edge pixels, which might cause false alarms during the edge detection

这是一切结束时的样子(边缘 block 已填充为黑色):

alt text

如果我跳过最后一步,这就是我所拥有的:

alt text

看来走上正轨了。因此,如果我对第 4 步进行侵 eclipse ,会发生以下情况:

alt text

我尝试了腐 eclipse 和膨胀的组合以获得与它们相同的结果,但没有接近。任何人都可以建议形态运算符的组合来获得我想要的结果吗?

这是二值化输出,以防有人想玩弄它:

alt text

如果您真的热衷于此,这里是源代码 (C++):

#include <cv.h>
#include <highgui.h>
#include <stdlib.h>
#include <assert.h>

using cv::Mat;
using cv::Size;

#include <stdio.h>

#define DCTSIZE 8
#define EDGE_PX 255

/*
* Display a matrix as an image on the screen.
*/
void
show_mat(char *heading, Mat const &m)
{
Mat clone = m.clone();

Mat scaled(clone.size(), CV_8UC1);
convertScaleAbs(clone, scaled);

IplImage ipl = scaled;

cvNamedWindow(heading, CV_WINDOW_AUTOSIZE);
cvShowImage(heading, &ipl);
cvWaitKey(0);
}

/*
* Get the DC components of the specified matrix as an image.
*/
Mat
get_dc(Mat const &m)
{
Size s = m.size();
assert(s.width % DCTSIZE == 0);
assert(s.height % DCTSIZE == 0);

Size dc_size = Size(s.height/DCTSIZE, s.width/DCTSIZE);

Mat dc(dc_size, CV_32FC1);
cv::resize(m, dc, dc_size, 0, 0, cv::INTER_AREA);

return dc;
}

/*
* Detect the edges:
*
* Sobel operator
* Thresholding
* Morphological operations
*/
Mat
detect_edges(Mat const &src, int T)
{
Mat sobelx = Mat(src.size(), CV_32FC1);
Mat sobely = Mat(src.size(), CV_32FC1);
Mat sobel_sum = Mat(src.size(), CV_32FC1);

cv::Sobel(src, sobelx, CV_32F, 1, 0, 3, 0.5);
cv::Sobel(src, sobely, CV_32F, 0, 1, 3, 0.5);

cv::add(cv::abs(sobelx), cv::abs(sobely), sobel_sum);

Mat binarized = src.clone();
cv::threshold(sobel_sum, binarized, T, EDGE_PX, cv::THRESH_BINARY);

cv::imwrite("binarized.png", binarized);

//
// TODO: this is the part I'm having problems with.
//

#if 0
//
// Try a 3x3 cross structuring element.
//
Mat elt(3,3, CV_8UC1);
elt.at<uchar>(0, 1) = 0;
elt.at<uchar>(1, 0) = 0;
elt.at<uchar>(1, 1) = 0;
elt.at<uchar>(1, 2) = 0;
elt.at<uchar>(2, 1) = 0;
#endif

Mat dilated = binarized.clone();
//cv::dilate(binarized, dilated, Mat());

cv::imwrite("dilated.png", dilated);

Mat eroded = dilated.clone();
cv::erode(dilated, eroded, Mat());

cv::imwrite("eroded.png", eroded);

return eroded;
}

/*
* Black out the blocks in the image that contain DC edges.
*/
void
censure_edge_blocks(Mat &orig, Mat const &edges)
{
Size s = edges.size();
for (int i = 0; i < s.height; ++i)
for (int j = 0; j < s.width; ++j)
{
if (edges.at<float>(i, j) != EDGE_PX)
continue;

int row = i*DCTSIZE;
int col = j*DCTSIZE;

for (int m = 0; m < DCTSIZE; ++m)
for (int n = 0; n < DCTSIZE; ++n)
orig.at<uchar>(row + m, col + n) = 0;
}
}

/*
* Load the image and return the first channel.
*/
Mat
load_grayscale(char *filename)
{
Mat orig = cv::imread(filename);
std::vector<Mat> channels(orig.channels());
cv::split(orig, channels);
Mat grey = channels[0];
return grey;
}

int
main(int argc, char **argv)
{
assert(argc == 3);

int bin_thres = atoi(argv[2]);

Mat orig = load_grayscale(argv[1]);
//show_mat("orig", orig);

Mat dc = get_dc(orig);
cv::imwrite("dc.png", dc);

Mat dc_edges = detect_edges(dc, bin_thres);

cv::imwrite("dc_edges.png", dc_edges);

censure_edge_blocks(orig, dc_edges);
show_mat("censured", orig);
cv::imwrite("censured.png", orig);

return 0;
}

最佳答案

我无法想象任何形态学操作的组合会产生与假定正确的结果检测到的相同的边缘,将您的部分结果作为输入。

我注意到底层图像不同;这可能是您的结果如此不同的原因。 Lena 图像可以很好地指示结果类型,但不能用于比较。您有与原作者完全相同的图片吗?

关于c++ - 需要帮助实现特殊的边缘检测器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4526852/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com