How can I make an intermittent image outline?

In the problem I got an intermittent edge image, how could it close? in other words, make the curve continuous. And the shape can be any, because it is a shadow of the coutour.

enter image description here

+5
source share
6 answers

Here are some ideas that might interest you. I don’t want to code and debug the load on C ++ in OpenCV - often people ask questions and never log in again, or you spend hours working on something, and then they tell you that one sample image that they provided, was not at all representative of their actual images and the method, which he took 25 minutes to explain, is completely inappropriate.


One idea is morphological dilatation - you can do it on the command line like this using ImageMagick:

convert gappy.jpg -threshold 50% -morphology dilate disk:5 result.png 

enter image description here


Another idea is to find all end-of-line pixels with a hit-and-miss morphology. It is available in OpenCV, but I do it with ImageMagick to save encoding / debugging. Structuring elements are as follows:

enter image description here

Hopefully you will see that the first (leftmost) structuring element is the west end of the East-West line, and the second is the north end of the North-South line, etc. If you still haven't received it, the last one is the southwest end of the northeast direction to the southwest line.

Basically, I believe that the line ends and then extends them with blue pixels and overlays the original:

 convert gappy.jpg -threshold 50% \ \( +clone -morphology hmt lineends -morphology dilate disk:1 -fill blue -opaque white -transparent black \) \ -flatten result.png 

enter image description here

Here's a close-up on before and after:

enter image description here

You can also find single pixels without neighbors using the peaks structuring element, for example:

enter image description here

and then you can find all the peaks and expand them with red pixels as follows:

 convert gappy.jpg -threshold 50% \ \( +clone -morphology hmt Peaks:1.9 -fill red -morphology dilate disk:2 -opaque white -transparent black \) \ -flatten result.png 

enter image description here

Here is a close-up of the before and after:

enter image description here

Depending on how your original images look, you can apply these ideas iteratively until your circuit becomes intact — you may be able to detect this by filling in the flood and see if your circuit will “contain water” without flooding "everywhere."

Obviously, you make red peaks, and the blue line ends in both white and the outline - I just do it in color to illustrate my technique.

+4
source

Here is a slightly different approach to finish it with Imagemagick

1) Threshold and contour extension

 convert 8y0KL.jpg -threshold 50% -morphology dilate disk:11 step1.gif 

enter image description here

2) Erode less

 convert step1.gif -morphology erode disk:8 step2.gif 

enter image description here

3) Pad 1 pixel around with black and fill the outside with white color and delete the padded 1 pixel around

 convert step2.gif -bordercolor black -border 1 -fill white -draw "color 0,0 floodfill" -alpha off -shave 1x1 step3.gif 

enter image description here

4) Erode by a smaller amount and get an edge on the white side of the transition. Notice that we started with extension 11, then we blew up by 8, then we are now blurred by 3. Thus, 8 + 3 = 11 will bring us back to the centerline.

 convert step3.gif -morphology erode disk:3 -morphology edgein diamond:1 step4.gif 

enter image description here

5) Create an animation to compare

 convert -delay 50 8y0KL.jpg step4.gif -loop 0 animation.gif 

enter image description here

+2
source

Mark Setchell is an interesting way to learn new material along the way. My approach is quite simple and straightforward.

I got the following solution. It includes a simple blur operation sandwiched between two morphological operations

I explained what I did with the code:

 #---- I converted the image to gray scale and then performed inverted binary threshold on it. ---- img = cv2.imread('leaf.jpg') gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(gray, 127, 255, 1) 

enter image description here

 #---- Next I performed morphological erosion for a rectangular structuring element of kernel size 7 ---- kernel = np.ones((7, 7),np.uint8) erosion = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel, iterations = 2) cv2.imshow('erosion', erosion ) 

enter image description here

 #---- I then inverted this image and blurred it with a kernel size of 15. The reason for such a huge kernel is to obtain a smooth leaf edge ---- ret, thresh1 = cv2.threshold(erosion, 127, 255, 1) blur = cv2.blur(thresh1, (15, 15)) cv2.imshow('blur', blur) 

enter image description here

 #---- I again performed another threshold on this image to get the central portion of the edge ---- ret, thresh2 = cv2.threshold(blur, 145, 255, 0) #---- And then performed morphological erosion to thin the edge. For this I used an ellipse structuring element of kernel size 5 ---- kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) final = cv2.morphologyEx(thresh2, cv2.MORPH_ERODE, kernel1, iterations = 2) cv2.imshow(final', final) 

enter image description here

Hope this helps :)

+1
source

Here is another suggestion that is more focused on "computer visualization."

As a general rule, the preprocessing step is usually a good idea to lose weight at all edges to make sure they are about 1 pixel thick. A popular thinning method is non-maximum suppression (NMS).

Then I would start by analyzing the image and finding all the related components that I have. OpenCV already provides a connectedComponents function. After defining the groups of connected components, you can place the Bezier curve in each group. An automatic method for fitting Bezier curves to a set of two-dimensional points is available in the Graphics Gem book. C code is also available there for its method. The goal of constructing a Bezier curve is to obtain the highest possible level of understanding of each group of components.

Then you need to combine these Bezier curves. A string join method using endpoint clustering is available from Shpitalni and Lipson . In this article, take a look at their adaptive clustering method in the "Object Linking and Endpoint Clustering" section.

Finally, with all the grouped curves you can fit the final Bezier curve as well as all the points you need to get a beautiful and natural map.

As an additional note, you can take a look at the work of Min-Min Cheng in cartoon extraction . OpenCV code for this method is also available here, but the following one-time application to your image will be displayed:

enter image description here

Denial of responsibility:
I can confirm the effectiveness of the Bezier curve fitting algorithm since I personally used it and it works very well. In addition, the Cheng curve extraction algorithm also works well, however, it will create poor looking “droplets” with thin contours due to the use of gradient detection (which tends to interpret thin lines!). If you could find a way around this thickening effect, you can skip extracting a Bezier curve and go straight to clustering endpoints to join the curves together.

Hope this helps!

+1
source

My suggestion:

  • find endpoints; these are pixels with no more than one neighbor after thinning to discard the “thick” endpoints. Endpoints must fall in pairs.

  • from all endpoints, enlarge the digital disk until you meet another endpoint that is not peer.

Instead of growing a disk, you can pre-process the set of endpoints and prepare it for finding the nearest neighbor (for example, a 2D tree). You will need to change the search to avoid getting to the point.

This approach does not depend on standard functions, but has the advantage that it follows the original plan.

In the image, the source pixels are white or green when they are the end points. Yellow pixels are segments of digital lines drawn between the nearest pairs of endpoints.

enter image description here

+1
source

You can try using remote conversion

 % binarize im=rgb2gray(im); im=im>100; % Distance transform bd=bwdist(im); maxDist = 5; bd(bd<maxDist)=0; bw=bwperim(bd); bw=imclearborder(bw); bw=imfill(bw,'holes'); bw=bwperim(bwmorph(bw,'thin',maxDist)); figure,imagesc(bw+2*im),axis image 

enter image description here

0
source

Source: https://habr.com/ru/post/1266496/


All Articles