19

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

Sample image

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

enter image description here

Jigar Parekh
  • 6,163
  • 7
  • 44
  • 64
  • Your first problem can be solved using findContours, since it only returns closed contours by definition. Your second problem can be solved by iterating over the contours using `contourArea()`, as I showed in my post, and selecting only those with areas above a certain threshold. – 1'' Apr 25 '13 at 16:10
  • I am developing the same type of app.Could you please help me? Thanks in advance – Jagdish Jun 24 '14 at 08:57
  • 1
    @jagdish look at post http://stackoverflow.com/questions/15082025/color-replacement-in-image-for-iphone-application – Jigar Parekh Jun 25 '14 at 07:23
  • @JigarParekh, One more question if you have idea. http://stackoverflow.com/questions/24378635/is-it-possible-to-map-the-2d-room-map-of-room-using-opencv-in-android. I posted this question on yesterday.Is it possible using android. but people giving negative mmark. Thanks in advance.. – Jagdish Jun 25 '14 at 07:46
  • @jagdish i think question is removed. – Jigar Parekh Jun 25 '14 at 15:23
  • @JigarParekh, Sorry.Actually people giving negative voting.So, I removed.Please check now undeleted it again. – Jagdish Jun 26 '14 at 04:54

5 Answers5

11

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

Thom
  • 495
  • 3
  • 12
  • Thanks i will tryout this, is there any way to identify and reject smaller contours? – Jigar Parekh Apr 24 '13 at 17:54
  • 1
    Take a look at [contourArea](http://docs.opencv.org/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contourarea#contourarea). With that, you should be able to reject the contours with too small area. – Oskar Birkne Apr 25 '13 at 12:11
  • 2
    I think it's a good idea to do Canny edge detection first and then use that as input for findContours, but it might work anyway. – Oskar Birkne Apr 25 '13 at 12:16
  • If you're not using the hierarchy, I'd go with `CV_RETR_LIST` over `CV_RETR_CCOMP`. Since the user only wants large contours, I'd probably just go directly to `CV_RETR_EXTERNAL` and get only the outermost contours in the hierarchy. – 1'' Apr 25 '13 at 16:08
9

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 :

Watershed with only short line keypoints

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 :

Better outline

And TADA! :

Pretty good result ;)

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

Hope that helps!

Community
  • 1
  • 1
Thom
  • 495
  • 3
  • 12
  • How you have added different contours in this image as I am trying to do the same in android but the result is totally different. Can you help me out? Email : areebthecomsian@gmail.com – Areeb Gillani May 11 '15 at 11:43
  • I just ran the sample file packaged with OpenCV, I don't think I changed much. What is you problem / output? – Thom May 18 '15 at 12:37
  • http://stackoverflow.com/questions/30295806/opencv-to-android-opencv-java Here is the problem – Areeb Gillani May 18 '15 at 14:01
4

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.

Community
  • 1
  • 1
  • 2
    problem with canny edge detection i am facing is getting lot of un-necessary small edge also detected and creating problem in color replacement any solution to that? – Jigar Parekh Apr 24 '13 at 17:53
  • can you help me with further solution, i have edited question with output of edge detection? – Jigar Parekh Apr 25 '13 at 11:16
  • For the canny edge detector you can approve the result by adjusting the sigma for the gaussian blur and the low and high thresholds. Then you might use HoughLines to find straight lines. – Bull Apr 26 '13 at 00:47
  • @JigarParekh I did not try it, but I got it while I was doing `OCR`. –  Apr 26 '13 at 03:37
  • @JigarParekh i am developing same kind of app in android and facing same problem could u help me how to do and what should be right concept to achieve this? thanks... – Prabhakar Jun 22 '15 at 04:50
2

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;
    }
}
1''
  • 26,823
  • 32
  • 143
  • 200
0

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.

denver
  • 2,863
  • 2
  • 31
  • 45