首页 > 解决方案 > 如何在图像上应用自定义过滤器?

问题描述

我在 WSL + XServer 上的 Ubuntu 20.04 LTS 上为 GUI 使用 OpenCV4。

我想创建自定义卷积过滤器内核并将它们应用于我的图像。这是我为它编写的代码:

cv::Mat filter2D(cv::Mat input, cv::Mat filter)
{
    using namespace cv;
    Mat dst = input.clone();
    //cout << " filter data successfully found.  Rows:" << filter.rows << " cols:" << filter.cols << " channels:" << filter.channels() << "\n";
    //cout << " input data successfully found.  Rows:" << input.rows << " cols:" << input.cols << " channels:" << input.channels() << "\n";

    for (int i = 0-(filter.rows/2);i<input.rows-(filter.rows/2);i++)
    {
        for (int j = 0-(filter.cols/2);j<input.cols-(filter.cols/2);j++)
        {  //adding k and l to i and j will make up the difference and allow us to process the whole image
            float filtertotal = 0;
            for (int k = 0; k < filter.rows;k++)
            {
                for (int l = 0; l < filter.rows;l++)
                {
                    if(i+k >= 0 && i+k < input.rows && j+l >= 0 && j+l < input.cols)
                    {  //don't try to process pixels off the edge of the map
                        float a = input.at<uchar>(i+k,j+l);
                        float b = filter.at<float>(k,l);
                        float product = a * b;
                        filtertotal += product;
                    }
                }
            }
            //filter all proccessed for this pixel, write it to dst
            dst.at<uchar>(i+(filter.rows/2),j+(filter.cols/2)) = filtertotal;
        }
    }
    return dst;
}

int main(int argc, char** argv)
{
  // Declare variables
    cv::Mat_<float> src;
    const char* window_name = "filter2D Demo";
    // Loads an image
    src = cv::imread("fapan.png", cv::IMREAD_GRAYSCALE ); // Load an image
    if( src.empty() )
    {
        printf(" Error opening image\n");
        return EXIT_FAILURE;
    }
    static float x[3][3] = {
        {-1, -1, -1},
        {-1,  8, -1},
        {-1, -1, -1}
    };
    cv::Mat kernel(3,3, CV_16FC1, x);
    // Apply filter
    filter2D(src, kernel);
    cv::imshow( window_name, src );
    cv::waitKey(0);
    return EXIT_SUCCESS;
}

问题是输出图像是这样的。 在此处输入图像描述

如您所见,不仅边缘是白色的,而且内部也是白色的。

输入图像 在此处输入图像描述

标签: c++opencvimage-processing

解决方案


您为输入代码发布的输出是正确的,因为您在图像上应用了普通过滤器。

它可能会导致它有点模糊或锐化,但它永远不会导致它完全检测到边缘。

为了只检测图像的边缘,您必须沿某个方向应用拉普拉斯算子。 https://www.l3harrisgeospatial.com/docs/LaplacianFilters.html#:~:text=A%20Laplacian%20filter%20is%20an,an%20edge%20or%20continuous%20progression。(带有一些信息的链接)这是图像的衍生物,它只会检测到变化。

我建议您在 matlab 图像处理工具箱上执行此操作。


推荐阅读