crop image into individual parts - python

I used semantic segmentation to color code the different elements in an image shown below.
In Python, I want to crop the original image into many small images based on the colors of the second image, so that the sofa becomes one cropped part, the lamp becomes one.etc. The overlap of the pillows on the sofa can be ignored. Say I have a 3D array of an image, I want to separate that array into the individual colored sections, and apply the coordinate of those elements in cropping the original image. How should I achieve this?

You can do it like this:
find the number of unique colours in the segmented image - see here
iterate over that list of colours making that colour white and everything else black, then findContours() to get the bounding box and save the contents of that bounding box as a PNG.

Related

finding simple rectangles in image, save and replace them

How could I find simple rectangles in image such as:
save them in separate picture files and replace them by a simple description such as:
Turn the image to binary by assigning white where you see the color of a rectangle and black elsewhere.
Detect the connected components and determine their bounding box.
Now you can replace the content of the image in these bounding boxes.
Repeat for every rectangle color.
There must be a rule to tell which text to write in which box. But you did not state that.
I assume this is an RGB image.
One possible solution would be to use OpenCV or Pillow to convert the image into an array (3 channels). Then set a threshold for the colours.
For example, the red colour is RBG=(255,0,0). You could set a threshold of more than 200 for the first channel and less than 5 for the second and third channels.
Then you determine the coordinates of the localised area and get the resulting array.
Then, you convert this array to white. So, replace this array with a new array (having the same dimension) with the white colour RGB=rgb(255,255,255).
Since you already know the position of the localised rectangle, you can label the new image with PIL, for example.

Create an image composed by different images

I have the a list of images (each of these image is a separate file), let's say they are some jigsaw puzzle pieces and, for each of them, I know it's position (x,y) and rotation in the complete puzzle.
How can I show the complete puzzle by stitching each of these pieces together in a single image (given that i know where to put each of them)?
I don't know if this is important but the pieces are not of regular shape (e.g. they are not squares), and they are all of different sizes
EDIT:
For the moments it seems to be working without the rotation but there is another problem, the pieces seems to not have a transparent background but rather a black one.
I have loaded them with opencv2 in the following way:
import glob
folder = './img/2/frag_eroded/'
frags = []
files = glob.glob(folder+"/*.png")
for file in files:
image = cv2.imread(file, cv2.IMREAD_UNCHANGED)
image = cv2.cvtColor(image, cv2.COLOR_BGRA2RGBA)
frags.append(image)
Example of resulting image, you can kinda see the the squares around each piece and see how the pieces overlap with their "background" that should be transparent rather then black
This depends on how you want to handle it when there's an overlapping transparent area.
Suppose all pixels are either transparent or opaque, and
Suppose each image has RGBA (4-channels including alpha),
then you can set all RGB values to zero whenever the pixel is transparent.
Then proceed to add the smaller images to a bigger canvas (initialized to be all zeros RGB). The canvas can either have an alpha layer or not, depending on your preference.
Beware the canvas is big enough to contain all of them. So the first step here would be to make a large enough matrix / opencv image.
How to add images: https://stackoverflow.com/a/68878529/19042045

Python - How to detect hard edges of multiple thumbnails and save the coordinates?

We have a scanned white page - A4 size that contains multiple thumbnails.
The thumbnails are similar but not exactly the same.
The thumbnails can be in random order and not in a very clear rows and columns. They are not totally random but they are in rows, however these are not a very accurate rows.
A4 page background color is white.
All thumbnails have black border of 5px and border-radius of 10 px
Everyone of the thumbnails contains a green circle (Could be in the center or somewhere close to that).
1. How can we detect the Hard Edges of every thumbnail and store the coordinates so we can crop the thumbnails for later processing and analyzing colors?
2. How can we detect the circle in the center. We want to analyze and get all pixels RGB values contained into this circle and then calculate average RGB value.
Update
This is the image:
Thank you
Main idea: As there are enough blank between the regions, so just crop each region by contours. Then for each region, use houghCircle to detect the circle in it.
Your image is this:
After find external contours and calculate the bounding boxes:
For each contour, crop and find hough circle in it.
Notice: I'll not provide my code for this question.
But post some links maybe useful for you. Learn and do by yourself:
Copy shape to blank canvas (OpenCV, Python)
cv2.drawContours() - unfill circles inside characters (Python, OpenCV)
How to detect colored patches in an image using OpenCV?
Edge detection on colored background using OpenCV
How can I get the minimum enclosing circle with OPENCV?
How can I prepare circle path text image for OCR program?
Update:
To detect the circle, you should select the right parameters, depends on your source image.
Try! Try! TRY!
Here is the circle detection I tried:
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT,
dp=1, minDist=20, circles=None,
param1=200 , param2=50,
minRadius=120, maxRadius=150
)

Crop out complementary regions from an image

I have coordinate regions of an image. I am cropping out images from those coordinates. Now, I need complimentary regions of what that is cut out, with respect to the original image. How do I go about using Pillow?
If you crop a region you basically create a new, smaller image.
A complementary operation to that would be to fill the region with some value you consider invalid or zero as you will still have an image of the original size. Technically you cannot remove a region from an image. you can just change or ignore it.
PIL.ImageDraw.Draw.rectangle(xy, fill=None, outline=None)
is something I found quickly. Maybe there is something better. Just crawl through the reference.

why are my contours not being totally filled in opencv?

I am processing video that looks like this (these are moving blobs):
I am successfully able to do basic processing in opencv to find contours around the blobs, draw circles around them, etc. Below is some tracking info drawn over an inverted image of the original video frame:
I would like to do a projection of these moving blob sequences, such that I get an image with a black trace of the blobs movement. I call this a blob track. I think I'm using the term "projection" correctly, because if this was a 3d stack it would be called a "z-projection" (only the projection this time is through time/frames in the video).
When I do this, I get an image of the blob track that is close to what I want, but there are tiny green pixels inside that I do not expect to be there considering I am filling a contour with black and then merging these filled contours. I get something like this:
Note the small green pixels present inside the blob track. They might seem subtle, but I don't want them there and can't figure out why they are there considering all I am doing in the code is stamping black blobs on top of one-another. The fact that they are green implies to me that they are part of the green background image on which I draw the blob tracks.
I know my filling is working because if I take a single frame instead of making a blob-track I get this, which looks good:
Something must be going wrong with the way I am doing the projection (addition of the filled contours through time).
The code for the single frame (working and shown up above) is:
cv2.drawContours(contourimage,bigbadlistofcontours[0],-1,(0,0,0),-1)
where contourimage is a green image the size of my frame, and bigbadlistofcontours[0] is the first entry in a list of my contours, and as you can see bigbadlistofcontours[0] contains two contours, which represent the two blobs, drawn successfully above.
The code for adding/projecting the multiple frames (not working and having these small green pixels inside) is:
for xx in bigbadlistofcontours:
cv2.drawContours(contourimage,xx[0],-1,(0,0,0),-1)
cv2.drawContours(contourimage,xx[1],-1,(0,0,0),-1)
#cv2.fillPoly(contourimage, pts =xx[0], color=(0,0,0))
#cv2.fillPoly(contourimage, pts =xx[1], color=(0,0,0))
As you can see I tried it using two methods - one using drawContours, and the other using fillPoly. Both produce small pixels inside the blob track that should not be there. Any idea what could cause these pixels to be there?
Make a small correction to your code and try below code:
for xx in bigbadlistofcontours:
cv2.drawContours(contourimage,[xx[0]],-1,(0,0,0),-1)
cv2.drawContours(contourimage,[xx[1]],-1,(0,0,0),-1)
Or simply try the following:
for xx in bigbadlistofcontours:
cv2.drawContours(contourimage,xx,-1,(0,0,0),-1)
findContours needs a list of contours as arguments, ie a list of numpy arrays. When you passed bigbadlistofcontours[0], it was a list of two numpy arrays ie, two contours. But when you pass xx the second time, you passed xx[0] which is a numpy array and xx[1] which is another numpy array. In that case, it will draw only a point in that numpy array, not full contours.
More Details on Contours

Categories

Resources