Image edge smoothing with opencv
Asked Answered
H

2

12

I am trying to smooth output image edges using opencv framework, I am trying following steps. Steps took from here https://mcmap.net/q/590091/-how-to-refine-or-blur-or-smooth-just-the-edges

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];

I want help whether if I am going in right way, or what am I missing?

Thanks for any suggestion and help.

Updated:

I have got an image like below got from grabcut algorithm, now I want to apply edge smoothening to the image, as you can see the image is not smooth. enter image description here

Hilltop answered 15/2, 2014 at 9:19 Comment(1)
@Boyko Perfanov I need help in it. I am trying to follow the steps you stated here https://mcmap.net/q/590091/-how-to-refine-or-blur-or-smooth-just-the-edgesHilltop
O
23

Do you want to get something like this?

enter image description here

If yes, then here is the code:

#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();
}

And I think this link will be interestiong for you too: Poisson Blending

Octopod answered 15/2, 2014 at 18:0 Comment(19)
Thanks for the answer, but I don't want output like this, I have updated my question, see if you can help please, thanks.Hilltop
I've changed my answer. Hope you'll catch the idea.Octopod
WHen I try to implement the above logic, I get something like this i.imgur.com/ClXXpbQ.png?1, it seems its doing things correctly but output is very different.. Any Idea.?Hilltop
It looks like a problem with CV_8UC3/CV_8UC1 and CV_32FC3/CV_32FC1 image types. The range for the first 0-255, range for the second one is 0-1. Try convert images you work with to CV_32FC3/CV_32FC1 type and scale it by factor 1.0/255.0 . I suspect that the values in mask image you used are in 0-255 range instead of 0-1.Octopod
Also I should mention that used images are: TestImage.jpg - is the image you povide above, lena.jpg - is initial image where you got TestImage.jpg from.Octopod
Yes exactly I am doing the same, the testimage in my case is the grabcut result I am getting, and lena is the original image.Hilltop
And what about image types and pixel value ranges?Octopod
Image type is CV_8UC1 not sure about pixel value rangesHilltop
You should convert it to CV_32FC1. And scale by factor 1.0/256.0 . All images should have real element type. I've done these conversions in the code above.Octopod
let us continue this discussion in chatHilltop
I am unable to get the output image, and can you please help me ?Hilltop
Can I see your code? You can send it to my email: andreysmorodovatlistdotru. Replace "at" and "dot" with "@" and ".".Octopod
@Hilltop Did you get something for edge smoothing?Amused
How do you save the result as a .bmp file ? I tried it but I get a very dark image.Radmen
Just multiply it by 255.In float format it is in 0-1 range.Octopod
can i get java solution of this answer?Supervisor
@AndreySmorodov"Poisson Blending" link has been broken.Supervisor
@Hilltop can you convert that code in java,it will be very helpful.Supervisor
Thanks! Link retargeted. Anyway you can find larger amount of papers and implementations on "poisson blending" or "compositing" keywords.Octopod
R
3

I have followed the following steps to smooth the edges of the Foreground I got from GrabCut.

  1. Create a binary image from the mask I got from GrabCut.
  2. Find the contour of the binary image.
  3. Create an Edge Mask by drawing the contour points. It gives the boundary edges of the Foreground image I got from GrabCut.
  4. Then follow the steps define in https://mcmap.net/q/590091/-how-to-refine-or-blur-or-smooth-just-the-edges
Revell answered 27/10, 2016 at 4:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.