I need to detect the option marked using OpenCV. Currently, I have been able to detect all the squares but the one that is marked. I have done this using the following piece of code.
canny = (cv2.Canny(roi_box, 30, 100))
cv2_imshow(canny)
img = roi_box.copy()
contours, heirarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cntsSorted = sorted(contours, key=lambda x:cv2.contourArea(x))
print("contours %i" % len(contours))
for i in range(45, 0, -1):
cv2.drawContours(img, cntsSorted[i], -1, (0, 255,0), 4)
if (cv2.contourArea(cntsSorted[i]) > 300):
cv2_imshow(img)
The area of the square that is marked is around 50. Can someone suggest to me how can I solve this problem?
For each channel (blue
, green
, red
), you can apply medianBlur
, Canny
, and bitwise-or
together.
img = cv2.imread("npDro.png")
bor = np.zeros(img.shape[:2], dtype="uint8")
for chn in cv2.split(img):
chn = cv2.medianBlur(chn, 11)
cny = cv2.Canny(chn, 50, 200)
bor = cv2.bitwise_or(bor, cny)
Result: (rescaled: w/2, h/2
)
Applying medianBlur
, Canny
and bitwise-or
operations are not must-do pre-processing. However, applying only Canny
or only MedianBlur
was not useful in this example. You may find another combination. The above code is just an example.
cnt = cv2.findContours(bor.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = imutils.grab_contours(cnt)
cnt = sorted(cnt, key=cv2.contourArea, reverse=True)[:4]
The reason I sorted the contours is that the text value If
is also detected. Therefore I get only the first four contours which are squares.
contour
draw the rectangle
.for (i, c) in enumerate(cnt):
M = cv2.moments(c)
cX = int(M["m30"] / M["m20"])
cY = int(M["m03"] / M["m02"])
cv2.rectangle(img,
pt1=(cX-30, cY-30),
pt2=(cX+20, cY+20),
color=(255, 0, 0), thickness=3)
Result:
Code:
import cv2
import imutils
import numpy as np
img = cv2.imread("npDro.png")
bor = np.zeros(img.shape[:2], dtype="uint8")
for chn in cv2.split(img):
chn = cv2.medianBlur(chn, 11)
cny = cv2.Canny(chn, 50, 200)
bor = cv2.bitwise_or(bor, cny)
cnt = cv2.findContours(bor.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnt = imutils.grab_contours(cnt)
cnt = sorted(cnt, key=cv2.contourArea, reverse=True)[:4]
for (i, c) in enumerate(cnt):
M = cv2.moments(c)
cX = int(M["m30"] / M["m20"])
cY = int(M["m03"] / M["m02"])
cv2.rectangle(img,
pt1=(cX-30, cY-30),
pt2=(cX+20, cY+20),
color=(255, 0, 0), thickness=3)
cv2.imshow("img", img)
cv2.waitKey(0)