Search code examples
pythonimageopencvimage-thresholdingssim

Extract the floor layout and threshold with OpenCV and Python


I've tried to use SSIM to extract the difference between two images to get only the floor area (image_a is the original and image_b has painted floor).

The output that was expected, is a threshold mask.

The problem I had was that the thresholding of ssim difference just didn't work in my case (example is shown below).

Can someone provide a better technique or theory of thresholding?

from skimage.measure import compare_ssim
import cv2
...

image_a = cv2.imread(first)
image_b = cv2.imread(second)

gray_a = cv2.cvtColor(image_a, cv2.COLOR_BGR2GRAY)
gray_b = cv2.cvtColor(image_b, cv2.COLOR_BGR2GRAY)

_, diff = compare_ssim(gray_a, gray_b, full=True, gaussian_weights=True)
diff = (diff * 255).astype("uint8")

thresh = cv2.threshold(diff, 0, 255,
                       cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]


if len(contour_sizes) > 0:
    largest_contour = max(contour_sizes, key=lambda x: x[0])[1]
    x, y, w, h = cv2.boundingRect(largest_contour)
    cv2.rectangle(image_a, (x, y), (x + w, y + h), (36, 255, 12), 2)
    cv2.rectangle(image_b, (x, y), (x + w, y + h), (36, 255, 12), 2)

cv2.imwrite('image_a.jpg', image_a)
cv2.imwrite('image_b.jpg',image_b)
cv2.imwrite('thresh.jpg', thresh)

image_a with max contour detected enter image description here image_b with max contour detected enter image description here thresh enter image description here


Solution

  • A better result can be obtained by thresholding the mean of the difference beetween given images.

    def get_mask(img1, img2, thresh):
        if img1.shape != img2.shape:
            return
        diff = cv2.absdiff(img1, img2)
        diff = np.mean(diff, axis=2)
        diff[diff <= thresh] = 0
        diff[diff > thresh] = 255
        mask = np.dstack([diff] * 3)
        return mask
    

    thresh_morph

    Artifacts may appear in the resulting mask and can be reduced by applying Morphological Transformations.