OpenCV图像边缘平滑处理

12

我正在尝试使用opencv框架平滑输出图像边缘,我正在尝试以下步骤。 步骤来自此处 https://dev59.com/WnPYa4cB1Zd3GeqPim6R#17175381

int lowThreshold = 10.0;
int ratio = 3;
int kernel_size = 3;

Mat src_gray,detected_edges,dst,blurred;

/// Convert the image to grayscale
cvtColor( result, src_gray, CV_BGR2GRAY );

/// Reduce noise with a kernel 3x3
cv::blur( src_gray, detected_edges, cv::Size(5,5) );

/// Canny detector
cv::Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size );

//Works fine upto here I am getting perfect edge mask    

cv::dilate(detected_edges, blurred, result);

//I get Assertion failed (src.channels() == 1 && func != 0) in countNonZero ERROR while doing dilate

result.copyTo(blurred, blurred);

cv::blur(blurred, blurred, cv::Size(3.0,3.0));

blurred.copyTo(result, detected_edges);

UIImage *image = [UIImageCVMatConverter UIImageFromCVMat:result];

我想知道是否我走在正确的路上,或者我缺少了什么?

感谢任何建议和帮助。

更新:

我得到了一张如下所示的grabcut算法生成的图像,现在我想对这张图像应用边缘平滑处理,因为你可以看到这张图像并不平滑。 enter image description here


@Boyko Perfanov 我需要帮助。我正在尝试按照您在此处提到的步骤进行操作https://dev59.com/WnPYa4cB1Zd3GeqPim6R#17175381 - iphonic
@herohuyongtao,你能帮忙吗? - iphonic
@berak 你能帮忙吗? - iphonic
2个回答

23

您想要得到这样的结果吗?

在此输入图像描述

如果是的话,以下是代码:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{
    cv::namedWindow("result");
    Mat img=imread("TestImg.png");
    Mat whole_image=imread("D:\\ImagesForTest\\lena.jpg");
    whole_image.convertTo(whole_image,CV_32FC3,1.0/255.0);
    cv::resize(whole_image,whole_image,img.size());
    img.convertTo(img,CV_32FC3,1.0/255.0);
    
    Mat bg=Mat(img.size(),CV_32FC3);
    bg=Scalar(1.0,1.0,1.0);

    // Prepare mask
    Mat mask;
    Mat img_gray;
    cv::cvtColor(img,img_gray,cv::COLOR_BGR2GRAY);
    img_gray.convertTo(mask,CV_32FC1);
    threshold(1.0-mask,mask,0.9,1.0,cv::THRESH_BINARY_INV);

    cv::GaussianBlur(mask,mask,Size(21,21),11.0);
    imshow("result",mask);
    cv::waitKey(0);


        // Reget the image fragment with smoothed mask
    Mat res;

    vector<Mat> ch_img(3);
    vector<Mat> ch_bg(3);
    cv::split(whole_image,ch_img);
    cv::split(bg,ch_bg);
    ch_img[0]=ch_img[0].mul(mask)+ch_bg[0].mul(1.0-mask);
    ch_img[1]=ch_img[1].mul(mask)+ch_bg[1].mul(1.0-mask);
    ch_img[2]=ch_img[2].mul(mask)+ch_bg[2].mul(1.0-mask);
    cv::merge(ch_img,res);
    cv::merge(ch_bg,bg);

    imshow("result",res);
    cv::waitKey(0);
    cv::destroyAllWindows();
}

我认为这个链接对你也会很有兴趣:泊松融合


谢谢你的回答,但我不想要这样的输出。我已经更新了我的问题,请看看能否帮忙,谢谢。 - iphonic
看起来是CV_8UC3/CV_8UC1和CV_32FC3/CV_32FC1图像类型的问题。第一个的范围是0-255,第二个的范围是0-1。尝试将你使用的图像转换为CV_32FC3/CV_32FC1类型,并按比例缩放1.0/255.0。我怀疑你使用的掩码图像中的值在0-255范围内,而不是0-1。 - Andrey Smorodov
是的,我正在做同样的事情,在我的情况下,testimage 是我获得的 grabcut 结果,而 lena 是原始图像。 - iphonic
你应该将它转换为CV_32FC1。并缩放因子为1.0/256.0。所有图像都应具有实数元素类型。我已经在上面的代码中完成了这些转换。 - Andrey Smorodov
1
@AndreySmorodov的“泊松混合”链接已经失效。 - EAS
显示剩余15条评论

3
我已经按照以下步骤平滑GrabCut获得的前景边缘:
  1. 从GrabCut获得的掩码创建二进制图像。
  2. 找到二进制图像的轮廓。
  3. 通过绘制轮廓点来创建Edge Mask。这会给出我从GrabCut获得的前景图像的边界边缘。
  4. 然后按照https://dev59.com/WnPYa4cB1Zd3GeqPim6R#17175381中定义的步骤操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接