Извлеките план этажа и порог с помощью OpenCV и Python

Я пытался использовать SSIM, чтобы извлечь разницу между двумя изображениями, чтобы получить только площадь пола (image_a — это исходное изображение, а image_b — нарисованный пол).

Ожидаемый результат — пороговая маска.

Проблема заключалась в том, что пороговое значение разницы ssim просто не работало в моем случае (пример показан ниже).

Может ли кто-нибудь предоставить лучшую технику или теорию пороговой обработки?

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 с обнаруженным максимальным контуром введите здесь описание изображения image_b с обнаруженным максимальным контуром введите здесь описание изображения thresh введите описание изображения


person arturkuchynski    schedule 04.10.2019    source источник
comment
Попробуйте размыть и расширить. Эта статья может дать вам некоторое представление. Проще говоря, настройте параметры эрозии и расширения, пока не будете удовлетворены результатом, а затем используйте метод findContours, чтобы получить площадь пола.   -  person Cabara    schedule 04.10.2019
comment
@陳翰群 Спасибо, это полезная статья, но она удаляет не все артефакты, которые у меня есть. Как насчет лучшего алгоритма извлечения различий?   -  person arturkuchynski    schedule 04.10.2019
comment
Кроме того, функции контура могут помочь вам отфильтровать части, которые вам не нужны. хочу. Например, вы можете искать контуры с большей площадью. В вашем случае вы хотите найти нижнюю часть и нижний правый угол. Эти две части имеют значительно большую площадь, чем другие артефакты.   -  person Cabara    schedule 04.10.2019
comment
Привет @arturkuchynski, я работаю над похожим проектом, не могли бы вы рассказать мне процесс или, по крайней мере, указать направление для достижения маскировки пола, как на втором изображении от первого изображения. Спасибо. Я много исследовал об этом, но не мог найти, в каком направлении двигаться. Блоги PyImageSearch OpenCV информативны, но не кажутся нужным мне решением.   -  person Lalit Fauzdar    schedule 14.06.2021


Ответы (1)


Лучший результат можно получить, установив пороговое значение среднего значения разницы между заданными изображениями.

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

В результирующей маске могут появиться артефакты, которые можно уменьшить, применив морфологические преобразования.

person arturkuchynski    schedule 07.10.2019