I have a series of images that are nothing more than a series of colored rectangles in a black background
Example:. How could I (using PIL in Python 3.7) make a program that would identify these rectangles (xy position, color and size)? Efficiency is not really important, so nested
for
s are acceptable. Every algorithm I've been able to come up with until now have a lot of flaws and can go wrong in many different ways, or are just WAY too complex and not at all worth it

- 51
- 8
2 Answers
I Don't know how far you are OK with OpenCV .
If your ready to use openCV , you can use the findContours to get the desired things .
Below is the code:
import cv2
readImage= cv2.imread(r"<ImagePath>\oKvDi.png")
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Code to Find edges of Square using Canny edge detection method and finding Contours and drawing in Back Line
edges = cv2.Canny(img_gray, 0, 100)
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#Just for your reference to show all rectangles are found
cv2.drawContours(readImage, contours, -1, (0, 0, 0), 5)
cv2.imwrite(r"<ImageSavePath>/a.png",readImage)
Hope this solves your problem

- 649
- 7
- 23
-
Thanks, I have no problem with using OpenCV, just said PIL in the question because I have a better idea of what I'm doing, so how can I get the data about the rectangles? again, I'm pretty much of a newbie in OpenCV. If I got it right `contours` are the key, but I have little to no idea what do do from here – Locked Mar 22 '19 at 03:10
-
As you have only rectangles in image , you just print `contours` to know the co-ordinates – Sreevathsabr Mar 22 '19 at 03:44
-
Well, after using `print(contours)` in another image with just 1 rectangle, I have this: http://prntscr.com/n1g2md , and there is the problem, I have no idea how to process all this data. It seems to be split in groups of 7, which is really confusing me – Locked Mar 22 '19 at 12:51
-
@Locked What actually your are trying to do with that co-ordinate? – Sreevathsabr Mar 22 '19 at 12:53
-
Just to have the top-left co-ordinates and size of the rectangles on the image, and print them, for a UI i'm making, and I don't want to have to re-check every time I change an element's position or size, so I'd just make the UI in a image-editing software, put it into this program, and it would output all I need to know to get the UI the way I want it – Locked Mar 22 '19 at 13:11
You don't need to write any code at all, you can do that with ImageMagick which is installed on most Linux distros and is available for macOS and Windows.
Just in the Terminal (Command Prompt on Windows), you can run:
magick convert image.png \
-define connected-components:verbose=true \
-define connected-components:area-threshold=100 \
-connected-components 4 -auto-level output.png
Sample Output
Objects (id: bounding-box centroid area mean-color):
0: 1200x714+0+0 651.2,369.3 703177 srgb(0,0,0)
164: 1200x86+0+714 599.5,756.5 103200 srgb(255,21,0)
2: 363x155+80+60 261.0,137.0 56265 srgb(255,255,255)
26: 127x323+60+302 122.6,463.2 39668 srgb(255,255,255)
54: 308x109+352+373 505.5,427.0 33572 srgb(255,255,255)
1: 102x159+641+47 691.5,126.0 16218 srgb(255,255,255)
53: 79x100+977+371 1016.0,420.5 7900 srgb(0,17,255)
So, looking at the line starting 0:
there is a rectangle measuring 1200x714 starting at 0,0 (top-left corner) with colour black, i.e. srgb(0,0,0).
Looking at the next line, there is a rectangle measuring 1200x86 starting 714 pixels down from the top-left corner with colour red, i.e. srgb(255,21,0).
And so on.
The last line is a rectangle 79x100 positioned at [977,31] with colour blue, i.e. srgb(0,17,255).

- 191,897
- 31
- 273
- 432
-
Well, I would rather have the code print out the UI line directly (something like "button = Button(340, 100, 20, 30, 'Ex. case')"), but thinking about it, since I can (and know how to) run os commands on python, get and parse the output, this is really helpful. Thanks. – Locked Mar 22 '19 at 23:15