I have this picture and I want to make a binary mask from it. The main (the biggest) rectangle should be white and other parts of the picture shound be black. Like this:
To solve this problem I want to find a contour of main rectangle. My plan is to find all external contours. Then get the contour with the highest area. Firstly, I tried to find all contours and plot them as a binary image. My attempt:
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import data, io
im = cv2.imread('train_1.jpg', 0)
contours, hierarchy = cv2.findContours(im.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
out = np.zeros_like(im)
cv2.drawContours(out, contours, -1, 255, 10)
io.imshow(out)
plt.show()
But even this simple code didn't find any contours. What's wrong with it? And how to get the contour with the highest area? Maybe I should apply Canny algorithm here? Please, help me.
You should the logic of taking the max area of rectangles as shown below. You can use this snippet to get the mask image of the area:
import cv2
import numpy as np
image = cv2.imread("jigsaw.jpg")
image = cv2.resize(image, (image.shape[1] // 4, image.shape[0] // 4))
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(blur, 255, 1, 1, 11, 2)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
max_area = 0
best_cnt = None
for counter in contours:
area = cv2.contourArea(counter)
if area > 1000:
if area > max_area:
max_area = area
best_cnt = counter
mask = np.zeros((gray.shape), np.uint8)
cv2.drawContours(mask, [best_cnt], 0, 255, -1)
cv2.drawContours(mask, [best_cnt], 0, 0, 2)
cv2.imwrite('mask_jigsaw.jpg', mask)
cv2.imshow("Image Mask", mask)
cv2.waitKey(0)