Reputation: 111
I followed different tutorials to recognize shapes in OpenCV but most of these tutorials just recognize shapes on a sheet of paper. I wanted to take it to the "next" level and recognize shapes in a real image. I thought that a simple next step would be to take an image of a brick wall and recognize all the bricks in it as they should have a fairly simple shape to recognize. I have been using the following image as an exercise:
My code is as follows:
import cv2
import numpy as np
img = cv2.imread("imgs/wall.jpeg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#cv2.imshow('gray', gray)
#cv2.waitKey(0)
edges = cv2.Canny(gray,190,200,apertureSize = 3)
cv2.imshow('edges',edges)
cv2.waitKey(0)
_, contours,h = cv2.findContours(edges, 1,2)
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
if len(approx)==4:
cv2.drawContours(img,[cnt],0,(0,0,255),2)
cv2.imshow("img", img)
cv2.waitKey(0)
So the first thing I thought was to get all the edges of this wall with canny edge detector. This gives me the following image:
On this image we can clearly see all the rectangles so my thought was that it would be rather easy to find all these rectangles by looking for contours. But it turns out this isn't the case. If i look for contours I get the following:
Which is clearly not what I want. I've been trying different things like blob detector or hough lines too but none seem to be working. I would really be happy if someone could give me some tips or even show me how it should be done! Thanks in advance!
Upvotes: 1
Views: 2917
Reputation: 111
Okay so based on @Photon and @Silencer, I got the following result now:
There is stil a small patch that isn't recognized but all the rest seem to be recognized.
If someone is interested in my code here it is:
import cv2
import random
img = cv2.imread("imgs/wall.jpeg")
# To hsv
hsv =cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
# Get the Saturation out
S=hsv[:,:,1]
# Threshold it
(ret,T)=cv2.threshold(S,42,255,cv2.THRESH_BINARY)
# Show intermediate result
cv2.imshow('win',T)
cv2.waitKey(0)
# Find contours
_, contours,h = cv2.findContours(T, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#img2 = img.copy()
for c in contours:
area = cv2.contourArea(c)
# Only if the area is not miniscule (arbitrary)
if area > 100:
(x, y, w, h) = cv2.boundingRect(c)
# Uncomment if you want to draw the conours
#cv2.drawContours(img, [c], -1, (0, 255, 0), 2)
# Get random color for each brick
tpl = tuple([random.randint(0, 255) for _ in range(3)])
cv2.rectangle(img, (x, y), (x + w, y + h), tpl, -1)
cv2.imshow("bricks", img)
cv2.waitKey(0)
Upvotes: 4
Reputation: 3222
Here's one direction: Assuming image is in I
J=cv2.cvtColor(I,cv2.COLOR_BGR2HSV)
S=J[:,:,1]
(ret,T)=cv2.threshold(S,32,255,cv2.THRESH_BINARY)
cv2.imshow('win',T)
cv2.waitKey()
Upvotes: 1