Как разделить изображения с помощью алгоритма водораздела в Python - PullRequest
4 голосов
/ 09 января 2020

Как разделить отдельные изображения между несколькими изображениями после сегментации изображения с использованием алгоритма водораздела в Python Прикрепленное изображение состоит из 4 изображений, из которых нам нужно применить сегментацию изображения и отделить отдельное изображение от этих 4 изображений enter image description here

Ответы [ 2 ]

5 голосов
/ 09 января 2020

Сначала заполним заливку

import cv2;
import numpy as np;

# Read image
im_in = cv2.imread("2SNAT.jpg", cv2.IMREAD_GRAYSCALE);

# Threshold.
# Set values equal to or above 220 to 0.
# Set values below 220 to 255.

th, im_th = cv2.threshold(im_in, 220, 255, cv2.THRESH_BINARY_INV);

# Copy the thresholded image.
im_floodfill = im_th.copy()

# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)

# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (0,0), 255);

# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)

# Combine the two images to get the foreground.
im_out = im_th | im_floodfill_inv

Filled image

Затем найдем контур и обрежем

im, contours, hierarchy = cv2.findContours(im_out.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

final_contours = []
for contour in contours:
    area = cv2.contourArea(contour)
    if area > 1000:
        final_contours.append(contour)

Обрезать шаг, также рисуя прямоугольник на исходном изображении

counter = 0        
for c in final_contours:
    counter = counter + 1
# for c in [final_contours[0]]:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.01 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    print(x, y, w, h)
    aspect_ratio = w / float(h)

    if (aspect_ratio >= 0.8 and aspect_ratio <= 4):
        cv2.rectangle(im_in,(x,y),(x+w,y+h),(0,255,0),2)
        cv2.imwrite('splitted_{}.jpg'.format(counter), im_in[y:y+h, x:x+w])
cv2.imwrite('rectangled_split.jpg', im_in)

Drawed square Result

3 голосов
/ 10 января 2020

Вместо использования водораздела, вот простой подход, использующий порог + морфологические операции. Идея состоит в том, чтобы получить двоичное изображение, а затем выполнить морфинг, чтобы объединить каждый объект в единый контур. Затем мы находим контуры и извлекаем / сохраняем каждый ROI, используя Numpy срезы.

Вот каждый отдельный объект, выделенный зеленым цветом

enter image description here

Индивидуальный сохраненный объект

enter image description here enter image description here enter image description here enter image description here

Код

import cv2

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Morph close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=3)

# Find contours and extract ROI
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
num = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    ROI = original[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(num), ROI)
    num += 1

cv2.imshow('image', image)
cv2.waitKey()
...