How to close a contour with OpenCV when dilating isn't enough - python

I have been looking to close contour for shapes that are similar to circles or rounded objects.
I found a very interesting answer here.
I thought my problem was solved until I tested with different images.
This is my mask from OpenCV canny AFTER dilating. As you can see, there is a big gap at the bottom.
If the shape was a circle, I could try to recreate the circle, but the thing is the shape could be different. I could look like a cucumber or a rugby balloon.
I wonder if it's actually possible to connect the contour without doing a straight line, which will make me lose a lot of information.
Approximating the "curveness" or "straightness" according to the neighbor?

Related

Finding contour around a cluster of pixels

I have a set of images that look like this:
Using python need a way to find a contour around the yellow shape that ignores the isolated points and is not too complex. Something looking a bit like this :
I tried some methods such as the find_contours function from skimage,which gives this after keeping only the biggest contour:
which is not what I am looking for. A also tried active contour (snake) which had the problem of paying too much attention to isolated pixels. Is there a particular method that would help me in this situation ?
Thank you
Assuming the yellow blob is slightly different across your images, I recommend you look into either using Morphological Operations, or using Contour Approximation.
I've never used scikit-image, but it appears to have Morphological functionalities included.
You can take a look at this OpenCV tutorial for a quick guideline of the different operations.
But I think all you need is to use the "Opening" operation to preprocess your yellow shape; making it smoother and removing the random speckles.
Another approach is by approximating that contour you've extracted to make it smoother. For scikit-image, that is the measure.approximate_polygon function. Also another OpenCV tutorial for reference on how Contour Approximation works (the same algorithm as with scikit-image).

OpenCV: Recognizing the Orientation of a Cube in a 2D Image

I'm looking forward to developing a Rubik's Cube solver (just for fun). For this, the user would take a picture of the cube in a way that three sides of it are visible, like in this picture:
cubeA.jpg:
It can be safely assumed that the cube is covering most of the picture. Now, what I would like to do is detect the exact orientation of the cube. That is, I am interesting in detecting these seven points:
cubeB.jpg:
From this, I would be able to split each of the three faces into 3x3 grid and detect the colors (for which I have already written the code and which works quite well).
Now, I have made a few attempts to solve this problem using corner detection and contour extraction in OpenCV. None of them have been satisfactory, however. Another way of looking at this problem would be to recognize each of the 27 little, so-called “facelets”, and detect the orientation using those. But I'm not sure if that's the right approach either.
How would you go about solving this problem using OpenCV?

How do I split a shape with conected pixels in to two parts in a binary image

My goal is to draw a rectangle border around the face by removing the neck area connected to the whole face area. All positive values here represent skin color pixels. Here I have so far filtered out the binary image using OpenCV and python. Code so far skinid.py
Below is the test image.
Noise removals have also been applied to this binary image
Up to this point, I followed this paper Face segmentation using skin-color map in videophone applications. And for the most of it, I used custom functions rather than using built-in OpenCV functions because I kind of wanted to do it from scratch. (although some erosion, opening, closing were used to tune it up)
I want to know a way to split the neck from the whole face area and remove it like this,
as I am quite new to the whole image processing area.
Perform a distance transform (built into opencv or you could write by hand its a pretty fun and easy one to write using the erode function iteratively, and adding the result into another matrix each round, lol slow but conceptually easy). On the binary image you presented above, the highest value in a distance transform (and tbh I think pretty generalized across any mug shots) will be the center of the face. So that pixel is the center of your box, but also that value (value of that pixel after the distance transform) will give you a pretty solid approx face size (since it is going to be the pixel distance from the center of the face to the horizontal edges of the face). Depending on what you are after, you may just be able to multiply that distance by say 1.5 or so (figure out standard face width to height ratio and such to choose your best multiplier), set that as your circle radius (or half side width for a box) and call it a day. Comment if you need anything clarified as I am pretty confident in this answer and would be happy to write up some quick code (in c++ opencv) if you need/ it would help.
(alt idea). You could tweak your color filter a bit to reject darker areas (this will at least in the image presented) create a nice separation between your face and neck due to the shadowing of the chin. (you may have to dial back your dilate/ closing op tho)

Smoothen edges of a non-binary image

I'm making some photo-editing tools in python using PIL (Python Imaging Library), and I was trying to make a program which converts a photo to its 'painted' version.
I've managed to make a program which converts a photo into its distinct colours, but the problem is that the algorithm I'm using is operating on every pixel, meaning that the resulting image has very jagged differences between colours.
Ideally, I'd like to smoothen out these edges, but I don't know how!
I've checked out this site for some help, but the method there produces quite different results to what I need.
My Starting Image:
My Image with Distinct Colours:
I would like to smoothen the edges in the image above.
Results of using the method which doesn't quite work:
As you can see, using the technique doesn't smoothen the edges into natural-looking curves; instead it creates jagged edges.
I know I should provide sample output, but suprisingly, I haven't actually got it, so I'll describe it as best as I can. Simply put, I want to smoothen the edges between the different colours.
I've seen something called a Gaussian blur, but I'm not quite sure as to how to apply it here as the answers I've seen always mention some sort of threshold, and are usually to do with binary images, so I don't think it can apply here.
Edge enhancement does the opposite of edge smoothing, so this is certainly not the tool you should use.
Unfortunately, there is little that you can do because edge smoothing will indeed smoothen the jaggies, but it will also destroy the true edges, resulting in a blurred image. Edge-preserving smoothing is also a dead-end.
You should have a look at the methods to extract the "cartoon part" of an image. There is a lot of literature on this topic, though often pretty sophisticated.
You can enhance the quality of your "Image with Distinct Colours" by applying a median filter with a radius of 2:
If you want to get "comic-like" dark edges, you can calculate the edges of the original image using a sobel filter, convert the edge map to grayscale, then multiply the resulting edge map with 2, inverse the map and add each non-white pixel of the edge map to the original image. This will result in:
This is of course only a starting point as the result leaves much to be desired, but it should give you a good idea about the basic concept.

Smoothing the edge in a large scale

I have images of eyes and eyebrows like the following one.
And I want it to be processed to be more smooth on the edges like the following one, which is drawn by hand.
I've tried with morphology opening, but with different size of the SE, it either fills the unexpected area or leaves with some rough edges. Here's the result with circle SE of size 9 and 7 respectively.
Another idea is to calculate the Convex Hull of the eyebrow and fill the color. But since the eyebrow is usually bending and the Convex Hull will become something like the following image, which is also not very ideal.
Or should I make every pixel on the edge to be a vertex of a polygon and then smooth the polygon? Any specific idea here?
Any idea how can I get the result in the second image?
I'm using Python OpenCV. Code or general idea are both welcomed. Thanks!

Categories

Resources