需要帮助实施特殊的边缘检测器
我正在从一篇研究论文中实施一种方法。 部分方法需要一个主要的边缘检测器,作者描述如下:
请注意,这不是 Canny边缘检测 - 它们不会打扰非最大抑制等事情。我当然可以用Canny边缘检测来做到这一点,但我希望按照文中所表达的内容来实现。
最后一步是我有点卡住了。
这正是作者对此所说的:
在从边缘检测过程获得二值边缘图之后,采用二值形态学操作去除孤立的边缘像素,这可能在边缘检测期间引起误报警
以下是所有事情应该看起来如何(边缘块已填充为黑色):

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

这似乎是在正确的轨道上。 所以,如果我为步骤4做了腐蚀,会发生什么情况:

我尝试过腐蚀和膨胀的组合,以获得与他们相同的结果,但不要靠近。 任何人都可以提出形态运算符的组合,这将使我获得期望的结果吗?
这里是二值化输出,以防有人想玩弄它:
如果你真的很热心,这里是源代码(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图像适用于指示结果的类型,但不适用于比较。 你有与原作者完全相同的图像吗?
作者描述的可以通过使用8way连接的连接组件分析来实现。 我不会称这种形态。
我认为你错过了其他的东西:他们的图像没有比一个像素厚的边缘。 你的。 您所引用的段落只是讨论去除孤立像素,所以必须有一个步骤您错过或实施不同。
祝你好运!
  我认为你需要的是一种侵蚀或开放,即从某种意义上说是4路而不是8路。  OpenCV的默认形态内核是一个3x3的矩形( shape = CV_SHAPE_RECT IplConvKernel )。  这在薄边上非常苛刻。 
  您可能想尝试使用shape = CV_SHAPE_CROSS的3x3自定义IplConvKernel侵蚀。  如果你需要一个更精细的过滤器,你可能想尝试使用4个不同的CV_SHAPE_RECT内核,大小为1x2,2x1,锚点分别为(0,1)和(1,0)。 
上一篇: Need help implementing a special edge detector
下一篇: How to check if a checkbox in a checkbox array is checked with jquery
