0

I'm learning how to recognize shapes that're within image provided. I'm able to recognize shape by number of edges present to the geometrical body. But now I'm wondering is there any way to differentiate between square and rectangle within image? Here's my code. Currently I'm just drawing contours to the geometrical figures.

import cv2

raw_image = cv2.imread('test1.png')
cv2.imshow('Original Image', raw_image)
cv2.waitKey(0)

bilateral_filtered_image = cv2.bilateralFilter(raw_image, 5, 175, 175)
cv2.imshow('Bilateral', bilateral_filtered_image)
cv2.waitKey(0)

edge_detected_image = cv2.Canny(bilateral_filtered_image, 75, 200)
cv2.imshow('Edge', edge_detected_image)
cv2.waitKey(0)

_, contours, hierarchy = cv2.findContours(edge_detected_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contour_list = []
for contour in contours:
    approx = cv2.approxPolyDP(contour,0.01*cv2.arcLength(contour,True),True)
    area = cv2.contourArea(contour)
    if ((len(approx) >= 3)):
        contour_list.append(contour)

cv2.drawContours(raw_image, contour_list,  -1, (0,0,0), 2)
cv2.imshow('Objects Detected',raw_image)
cv2.waitKey(0)

This is sample image

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Nuance
  • 101
  • 2
  • 14
  • 1
    It would be better if you can upload some sample input images, preferably the binary ones, Also, are your figures rotated ? – ZdaR Nov 13 '17 at 05:01
  • Yes shapes can be rotated with respect each others and there may be more than one shapes within same image – Nuance Nov 13 '17 at 05:02
  • Hem, maybe check equality of the sides. This is what differentiates a square from a rectangle. –  Nov 13 '17 at 09:17

4 Answers4

3

It is a square if its width and height are same. Otherwise its a rectangle.

for contour in contours:
    approx = cv2.approxPolyDP(contour,0.01*cv2.arcLength(contour,True),True)
    area = cv2.contourArea(contour)
    if ((len(approx) == 4)):
        (x, y, w, h) = cv2.boundingRect(approx)
        if  ((float(w)/h)==1):
            cv2.putText(raw_image, "square", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, 0, 2)
        else:
            cv2.putText(raw_image, "rectangle", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, 0, 2)

        contour_list.append(contour)

This change only detects squares and rectangles. Make necessary changes in the for loop to detect circles. You can work with len(approx) to make that distinction.

enter image description here

I.Newton
  • 1,753
  • 1
  • 10
  • 14
  • Exactly what I wished to do. I was looking for the function cv2.boundingRect(approx). I founded it on opencv docs. BTW thanks for the quick response. – Nuance Nov 13 '17 at 06:10
1

I have an alternate way:

  1. Find all the connected components.

  2. Find the feature points in the original image, since in this case we have simple geometrical bodies not complex objects, you can use corner points as feature points using Harris corner algorithm.

  3. Group these feature points lying on the same connected components.

  4. Use the relation(distance/angle) between these features points on all the connected components and accordingly you can classify these geometrical shapes.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
flamelite
  • 2,654
  • 3
  • 22
  • 42
1

The difference between a rectangle and a square is that a square has 4 equal sides making it a special rectangle. I learned this in kindergarden.

There are countless ways of identifying a square.

Its circumference always equals sqrt(area) hence its circularity is always 0.0625

The distance between all corners is either a or a * sqrt(2)

The centroid has the same distance a / 2 to all 4 sides

...

You name it.

Piglet
  • 27,501
  • 3
  • 20
  • 43
0

I read in the comments that the shapes might be rotated. In that case cv2.boundingRect() will not give correct results as this function always gives an upright rectangle. For detecting rectangles in general, (rotated or not), you should try cv2.minAreaRect() which will return a rectangle which will be rotated according to the contour and will have the minimum area to cover the contour. You can then check its aspect ratio to see if it is a square or a rectangle.

Ojas.M
  • 1
  • 1