How can I merge rectangles with small area (OpenCV, Python) - python

I'm using OpenCV in order to detect rectangles in my image so I can crop them later: (rectangles contains products).
The first thing I have done was detecting Vertical and Horizontal lines, combine them to get this picture : Image_With_Small_rectangles
As you can see on the left side of my image, I have got some indesirable vertical/horizontal lines, that create small rectangles.
As I'm new to OpenCV, I want to know if it's possible to merge rectangle with a small area! (if area > min_area) merge_rectangle
So I can get an image clean like this one : Clean_Image
Many thanks in advance!

Related

How can I crop a specific area of an image using Python?

This is an image containing some text, then a text box, then a Signature & after that a bottom line ending the picture.
And the 2nd image is what I want as output using python.
I have several pictures like this, I want the same cropped output for all the images.
Here is what I tried: I used pytesseract to OCR the image 1st to locate the text box determining that as starting point & thresholding to determine the endpoint of the signature area....then tried using OpenCV to crop that area & saving it in a local directory but the approach is not much promising.
Can someone help me to solve the problem?
There are several relatively simple approaches you could try.
You could use cv2.findContours() to locate the two big black titles "Additional Information" and "Signatures and Certifications" and scale off their position to deduce where the signature is. Your intermediate image might be like this:
You could use "Hit and Miss" matching to locate the 4 corners of the box "The IRS doesn't require your consent...".
You could do flood-fills in say, red, starting from white pixels near the centre of the image till you get a red box filled around the right size for the box "The IRS doesn't require your consent...". Then scale from that.
You could do a flood-fill in black, starting 2/3 of the way down the image and half way across, then find the remaining white area which would be the box "The IRS doesn't require...".
You could look for the large, empty white area below the signature (using summation across the rows) and scale off that. I am showing the summation across the rows to the right of the original image. You could invert first and look for black. Do the summation with:
rowTotals = np.sum(img, axis=1)

Interpolating colors inside a contour in opencv [python]

I am dealing with some images which contain tables and there are 1 or 2 stickers on them. What I am trying to do is getting rid of those stickers. Using color thresholding (in HSV) and contour detection I am able to create a mask for those stickers. Now I want those stickers to "dissolve" out from there (I don't know the correct term for this). While keeping those tables lines intact, so that my line detection works well (which I have to do after this cleaning).
I tried OpenCV's inpaint. But this doesn't work well here, because the sticker size is big enough.
See this example:
Part of the whole image where the sticker is sticking (inside contents are censored by me). It can be over horizontal lines, or vertical lines, or both. Basically, it's sticking somewhere on the table (maybe over some text too, but that can't be recovered anyway). The background won't be necessary whitish, it can be pink/orange/other colors.
This is the thresholded image, creating a mask of the sticker. We can also get the contour of this if required.
This is the result of cv.inpaint() with radius 3.
What I want is to reconstruct those lines.
My solution
Now my approach is to interpolate the colors in between the sticker contour, to fill it up. For each pixel inside the contour, I will do a vertical interpolation and a horizontal interpolation (interpolation of the boundary colors) and then fill that pixel with the average of both. I am hoping that this will preserve my vertical and horizontal lines at least. (Might fail if it's on a corner of the table). This will also keep the background smooth, my background can have some different colors.
Now my problem is how I can implement this. What I have are contours that I find using OpenCV's get_contours(). I don't know how to get the colors on its boundary and how to interpolate the in-between colors.
Any help is appreciated. Thanks in advance.
Due to confidentiality, I cannot share the whole image.
EDIT
I tried the seam-carving method (implementation). Here are the results:
Vertical seaming
Horizontal seaming
It works well once I know which one to use. And I am not sure how well it will do when we have both horizontal and vertical lines.
PS. Don't suggest a solution which needs to find lines and then work. Because there will be many lines in my whole image.
You can make synthetic example images. To better explain your issue.
As I got it you can use Poisson image editing. Just take a piece of clear paper image and paste it using poisson blending and the mask you extracted.
Check this github repo as instance for examples with code.

Fill Contour/Pixels within other Contours | Detecting Boxes using Depth Images

I'm using OpenCV to find boxes within a depth grayscale image.
First, I cut the depth image from the top of the box as shown below:
Next, I cut the depth image from the bottom of the box as shown below:
After some filtering, closing and doing some basic operations, I get an image of the top cut merged with where the box bottoms are along with bounding boxes. Please see the image below:
The goal now is to attempt to stretch the inner rectangles until they touch the corners of the top edges. The issue is that the boxes could be rotated which makes filling much harder than just looping horizontally/vertically and filling in gaps.
An approach would be getting a side of the inner rectangle, keep moving it in the direction of stretching until it touches some pixels of value 255. However, this takes a lot of time and isn't efficient.
Another approach is eliminating all pixels that aren't along the direction of stretching the segment, finding the contours of the remaining objects, and attempting the same method.
A third approach and the one that makes most sense to me:
Draw the other 2 segments connected to the side of the rectangle but as lines so to fill the entire image.
Anything outside the 2 lines is ignored
Find get a list of coordinates of the contours of the remaining objects in the direction of stretching/filling
Find the closest pixel to the side; this is where we'll stretch the box to
This is still rather inefficient.
Any help, guidance, or insights would be much appreciated. Thank you!

How to detect edge of object using OpenCV

I am trying to use OpenCV to measure size of filament ( that plastic material used for 3D printing)
What I am trying to do is measuring filament size ( that plastic material used for 3D printing ). The idea is that I use led panel to illuminate filament, then take image with camera, preprocess the image, apply edge detections and calculate it's size. Most filaments are fine made of one colour which is easy to preprocess and get fine results.
The problem comes with transparent filament. I am not able to get useful results. I would like to ask for a little help, or if someone could push me the right directions. I have already tried cropping the image to heigh that is a bit higher than filament, and width just a few pixels and calculating size using number of pixels in those images, but this did not work very well. So now I am here and trying to do it with edge detections
works well for filaments of single colour
not working for transparent filament
Code below is working just fine for common filaments, the problem is when I try to use it for transparent filament. I have tried adjusting tresholds for Canny function. I have tried different colour-spaces. But I am not able to get the results.
Images that may help to understand:
https://imgur.com/gallery/CIv7fxY
image = cv.imread("../images/img_fil_2.PNG") # load image
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # convert image to grayscale
edges = cv.Canny(gray, 100, 200) # detect edges of image
You can use the assumption that the images are taken under the same conditions.
Your main problem is that the reflections in the transparent filament are detected as edges. But, since the image is relatively simple, without any other edges, you can simply take the upper and the lower edge, and measure the distance between them.
A simple way of doing this is to take 2 vertical lines (e.g. image sides), find the edges that intersect the line (basically traverse a column in the image and find edge pixels), and connect the highest and the lowest points to form the edges of the filament. This also removes the curvature in the filament, which I assume is not needed for your application.
You might want to use 3 or 4 vertical lines, for robustness.

Combine two overlapping videos frame by frame to form a single frame

I am getting video input from 2 separate cameras with some area of overlap between the output videos. I have tried out a code which combines the video output horizontally. Here is the link for that code:
https://github.com/rajatsaxena/NeuroscienceLab/blob/master/positiontracking/combinevid.py
To explain the problem visually:
The red part shows the overlap region between two image frame. I need the output to look like the second image, with first frame in blue and second frame in green (as shown in third illustration)
A solutions I can think of but unable to implement is, Using SIFT/SURF find out the maximum distance keypoints from both frames and then take the first video frame completely and just pick the non overlapping region from second video frame and horizontally combine them to get the stitched output.
Let me know of any other solutions possible as well. Thanks!
I read this post one hour ago. I tried some really easy approach. Not perfect but in some cases should work well. For example, if you have both cameras on one frame placed side by side.
I took 2 images from the phone like on a picture (color images). Program select Rectangles region from both source images and resize end extract this roi rectangles. The idea is to find the "best" overlapping Rect regions by normalized correlation.
M1 and M2 is mat roi to compare,
matchTemplate(M1, M2, res, TM_CCOEFF_NORMED);
After, I find this overlapping Rect use this to crop source images and combine by hconcat() function together.
My code is in C++ but is really simple to replicate this in python. It is not the best solution but one of the most simple solution. If your cameras are fixed in stable position between themselves. This is a good solution I think.
I hold my phone in hand :)
You can also use this simple approach on video. The speed depends only on the number of rectangle candidate you compare.
You can improve this by smart region to compare selection.
Also, I am thinking about another idea to use optical flow by putting your images from a camera at the same time to sequence behind each other. From the possible overlapping regions in one image extract good features to track and find them in the region of second images.
Surf and sift are great for this but this is the most simple idea on my mind.
Code is Here Code

Categories

Resources