Is there a way to get content inside the box (dashed red rectangle I've noted) based on 4 small squares around it?
My code:
# Read and resize image
img_input = cv2.imread(args.pop('image'), )
img_input_height, img_input_width, _ = img_input.shape
img_input_ap = img_input_width / img_input_height
img_input_width = int(const_image_max_height * img_input_ap)
img_input = cv2.resize(img_input, (img_input_width, img_input_height,), )
# Process image color
img_final = img_input.copy()
img_gray = cv2.cvtColor(img_input, cv2.COLOR_BGR2GRAY, )
img_blur = cv2.GaussianBlur(img_gray, (5, 5,), 5)
img_canny = cv2.Canny(img_blur, 10, 70, )
# Find around contours
img_canny_contours, _ = cv2.findContours(
img_canny,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE,
)
# Find square contours
img_preview = img_final.copy()
for contour in img_canny_contours:
rect = cv2.boundingRect(contour)
rect_width = rect[2]
rect_height = rect[3]
if 0.8 <= (rect_width / rect_height) <= 1.2:
# Now I founded the squares...
# Now I need to find the rectangle between 4 squares founded here...
cv2.imshow('img_preview', img_preview)
cv2.waitKey()
cv2.destroyAllWindows()
One way, considering that dashed line is not supported by OpenCV drawing functions.
First read the image in grayscale, blur and threshold:
blurred = cv2.GaussianBlur(im, (5, 5), 0)
threshold = 200
apply_val = 255
ret, th = cv2.threshold(blurred, threshold, apply_val, cv2.THRESH_BINARY)
Use findContorus function with cv2.RETR_CCOMP
as retrieval mode:
contours, hierarchy = cv2.findContours(th, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE)
Recover the vertex as center of the contours, skipping the first which is the image boundary:
vertex = []
for c in contours[1:]:
moment = cv2.moments(c)
cx = int(moment["m10"] / moment["m00"])
cy = int(moment["m01"] / moment["m00"])
vertex.append((cx, cy))
Now you need to sort the vertex, you can define a method that does, this is manual:
sorted_vertex = [vertex[1], vertex[0], vertex[2], vertex[3]]
vertex_rotated = sorted_vertex[1:] + sorted_vertex[:1]
vertex_pairs = list(zip(sorted_vertex, vertex_rotated))
You can draw a poly using sorted_vertex
or a sequence of lines using vertex_pairs
.
res = np.ones_like(im) * 255
res = cv2.cvtColor(res2, cv2.COLOR_GRAY2BGR)
for a, b in vertex_pairs:
cv2.line(res2, a, b, (0, 0, 255), 5)
Getting this result (Look on SO for a way to draw a dashed line):