当前位置: 动力学知识库 > 问答 > 编程问答 >

android - How detect long edges of wall to prepare mask and recolor

问题描述:

Main idea is to allow user to recolor to specific wall based user selection.

Currently i have implemented this feature using cvFloodFill (helps to prepare mask image) which can help me to change relative HSV value for wall so i can retain edges. but problem with this solution is that it works on color and all walls are repainted instead of single wall selected by user.

i have also tried canny edge detection but it just able to detect edge but not able to convert it to area.

Please find below code which i am currently using for repaint function

  1. Prepare mask

    cvFloodFill(mask, new CvPoint(295, 75), new CvScalar(255, 255, 255,0), cvScalarAll(1), cvScalarAll(1), null, 4, null);

  2. split channel

    cvSplit(hsvImage, hChannel, sChannel, vChannel, null);

  3. change color

    cvAddS(vChannel, new CvScalar(255*(0.76-0.40),0,0,0), vChannel, mask);

How can we detect edges and corresponding area from the image.

i am looking for solution which can be other than opencv but should be possible for iPhone and android

Edit

i am able to achieve somewhat result as below image using below steps

cvCvtColor(image, gray, CV_BGR2GRAY);

cvSmooth(gray,smooth,CV_GAUSSIAN,7,7,0,0);

cvCanny(smooth, canny, 10, 250, 5);

there are two problem with this output not sure how to resolve them

1. close near by edges

2. remove small edges

网友答案:

I think I might have the solution for you! There is a sample file called watershed.cpp in OpenCV, just run it and you'll get this result :

You can make your user draw on his screen to discriminate each wall. Then if you want something more precise you can outline the areas (without touching other lines) like this :

And TADA! :

With a little work you can make it user-friendly (cancel last line, connect areas etc...)

Hope that helps!

网友答案:

You could try something like :

 Mat imageOut = Mat::zeros(imageIn.rows, imageIn.cols, CV_8UC3);

 vector<vector<Point> > contours;
 vector<Vec4i> hierarchy;    

 findContours( imageIn, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
 for( int idx = 0; idx >= 0; idx = hierarchy[idx][0] )
 {
     Scalar color( rand()&255, rand()&255, rand()&255 );
     drawContours( imageOut, contours, idx, color, CV_FILLED, 8, hierarchy );
 }

It should draw the walls in different colors. If it works, that means that in "hierarchy" each wall is identified as a contour, you then will have to find out which one the user selected on his touch screen and do your color tuning processing.

You may have to change the different parameters in "findContours" link. You will also need to smooth the input image before the contour detection to avoid being annoyed with the details or textures.

Hope that helps, Thomas

网友答案:

I think you can use Canny Edge Detection algorithm to find edge difference. Some links

  1. StackOverFlow
  2. StackOverFlow
  3. OpenCV QA
  4. OpenCV
  5. Native Tutorial

I hope this can help you out. Thanks.

网友答案:

Here is some OpenCV4Android code to find the largest contour in a Mat called image, which we'll assume is in the RGBA colour space. To find contours, it's first necessary to threshold or binarize the image (convert to black and white). Using a Gaussian Blur on the image before thresholding reduces the number of small contours that are produced. The size parameters to the blur and threshold must be odd numbers; you can play around to find which value gives the best results (here, I've used 7 for both).

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
Mat BW = new Mat();
Mat hierarchy = new Mat();
MatOfPoint largestContour;

Imgproc.cvtColor(image, image, Imgproc.COLOR_RGBA2GRAY); // convert to grayscale

Imgproc.GaussianBlur(image, BW, new Size(7,7), 0); 

Imgproc.adaptiveThreshold(BW, BW, 255, 
    Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 7, 2.0);

Imgproc.findContours(BW, contours, hierarchy, Imgproc.RETR_EXTERNAL,
        Imgproc.CHAIN_APPROX_SIMPLE);

double maxArea = 0;
for (MatOfPoint contour : contours) {
    double area = Imgproc.contourArea(contour);
    if (area > maxArea) {
        maxArea = area;
        largestContour = contour;
    }
}
网友答案:

there are two problem with this output not sure how to resolve them 1. close near by edges 2. remove small edges

  1. You can use morphologic operations to close the edges. Look for the dilation and closing operators.

  2. You can remove small edges by doing labeling. Count the number of pixels in each region (connected white pixels). Remove any region with a number of pixels less than some threshold. I don't use opencv, but most libraries have a labeling function that will create an image where each set of touching pixels of a single color are assigned a unique color in the output image.

分享给朋友:
您可能感兴趣的文章:
随机阅读: