0

How to split the two rectangles in the image. Also to extract the coordinates of the rectangle with removing the extra projections. Contour detection gives the full image as a circle, instead of splitting it into two rectangles.enter image description here

Please find the input image,

enter image description here

detect_shapes.py

 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if imutils.is_cv2() else cnts[1] sd = ShapeDetector() for c in cnts: M = cv2.moments(c) cX = int((M["m10"] / M["m00"])) cY = int((M["m01"] / M["m00"])) shape = sd.detect(c) c = c.astype("float") #c *= ratio c = c.astype("int") cv2.drawContours(image, [c], -1, (0, 255, 0), 2) cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2) cv2.imshow("Image", image) cv2.waitKey(0) 

shapedetector.py

class ShapeDetector: def __init__(self): pass def detect(self, c): shape = "unidentified" peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * peri, True) if len(approx) == 3: shape = "triangle" elif len(approx) == 4: print("value of approx", approx) (x, y, w, h) = cv2.boundingRect(approx) ar = w / float(h) print("value of ar",ar) if (ar >= 0.95 and ar <= 1.05): shape = "Square" elif (ar <= 5 and ar >= 3): shape = "Obround" else: shape = "rectangle" elif len(approx) == 5: shape = "pentagon" elif len(approx) == 2: shape = "line" print("value of approx", approx) else: shape = "circle" print("value of approx", approx) return shape 

My required output is the below. enter image description here

5
  • provide your input image and code... Commented Apr 12, 2018 at 9:04
  • Please find the required details provided Commented Apr 12, 2018 at 9:18
  • and why do you think you shoudl get two separate objects? there is a pretty obvious line connecting both "rectangles". also note that your shape classification is non-sense. how is this a circle? Commented Apr 12, 2018 at 9:21
  • My requirement is to find only the rectangle, since there is a line connected i get the result as Circle. Kindly help me to remove the connecting line and get the required output as two rectangles. My shape classification is generic, if the len(approx) is greater than 5 i mean to get a circle. Commented Apr 12, 2018 at 9:30
  • 1
    You can apply opening morphology on thresholded image. docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/… Then you can find biggest contour Commented Apr 12, 2018 at 9:32

1 Answer 1

3

As Akhilesh suggested, a morphology OPEN operation will remove the line connecting the two rectangles. An excellent Python tutorial is here: https://docs.opencv.org/3.0.0/d9/d61/tutorial_py_morphological_ops.html. Use the smallest kernel size that will work for your application to prevent too much distortion. For your test image, I used a kernel size of 5.

detect_shapes.py:

import cv2 from shapedetector import ShapeDetector image = cv2.imread('rectangles.jpg') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1] ksize = 5 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize,ksize)) thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) cnts = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # ~ cnts = cnts[0] if imutils.is_cv2() else cnts[1] cnts = cnts[1] sd = ShapeDetector() for c in cnts: M = cv2.moments(c) if M["m00"] != 0: # prevent divide by zero cX = int((M["m10"] / M["m00"])) cY = int((M["m01"] / M["m00"])) shape = sd.detect(c) c = c.astype("float") #c *= ratio c = c.astype("int") cv2.drawContours(image, [c], -1, (0, 255, 0), 2) cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2) cv2.imshow("Image", image) cv2.waitKey(0) 

shapedetector.py:

import cv2 class ShapeDetector: def __init__(self): pass def detect(self, c): shape = "unidentified" peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * peri, True) if len(approx) == 3: shape = "triangle" elif len(approx) == 4: print("value of approx", approx) (x, y, w, h) = cv2.boundingRect(approx) ar = w / float(h) print("value of ar",ar) if (ar >= 0.95 and ar <= 1.05): shape = "Square" elif (ar <= 5 and ar >= 3): shape = "Obround" else: shape = "rectangle" elif len(approx) == 5: shape = "pentagon" elif len(approx) == 2: shape = "line" print("value of approx", approx) else: shape = "circle" print("value of approx", approx) return shape 

Output image:

output image

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.