Как удалить черную часть с изображения?

Я сшил два изображения вместе с помощью функций OpenCV и С++. Теперь я столкнулся с проблемой, что конечное изображение содержит большую черную часть.

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

enter image description here

Как удалить черный раздел?

Ответ 1

mevatron ответ - это один из способов, когда количество черной области минимизируется при сохранении полного изображения.

Другой вариант - удалить полную черную область, где вы также потеряете часть изображения, но результатом будет четкое прямоугольное изображение. Ниже приведен код Python.

Здесь вы найдете три основных угла изображения, как показано ниже:

enter image description here

Я отметил эти значения. (1,x2), (x1,1), (x3,y3). Он основан на предположении, что ваше изображение начинается с (1,1).

Код:

Первые шаги такие же, как mevatron. Размытие изображения для удаления шума, пороговое изображение, затем поиск контуров.

import cv2
import numpy as np

img = cv2.imread('office.jpg')
img = cv2.resize(img,(800,400))

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray,3)

ret,thresh = cv2.threshold(gray,1,255,0)
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)

Теперь найдите самый большой контур, который является вашим изображением. Во избежание шумов в случае, если они есть (скорее всего, их не будет). Или вы можете использовать метод mevatron.

max_area = -1
best_cnt = None

for cnt in contours:

    area = cv2.contourArea(cnt)
    if area > max_area:
        max_area = area
        best_cnt = cnt

Теперь приблизите контур, чтобы удалить ненужные точки в найденных значениях контура, но сохраняйте все угловые значения.

approx = cv2.approxPolyDP(best_cnt,0.01*cv2.arcLength(best_cnt,True),True)

Теперь мы находим углы.

Сначала найдем (x3, y3). Это самая дальняя точка. Поэтому x3*y3 будет очень большим. Итак, мы находим произведения всех пар точек и выбираем пару с максимальным произведением.

far = approx[np.product(approx,2).argmax()][0]

Далее (1, x2). Это точка, где первый элемент равен единице, тогда второй элемент максимален.

ymax = approx[approx[:,:,0]==1].max()

Далее (x1,1). Это точка, где второй элемент равен 1, тогда первый элемент является максимальным.

xmax = approx[approx[:,:,1]==1].max()

Теперь мы найдем minimum values in (far.x,xmax) and (far.y, ymax)

x = min(far[0],xmax)
y = min(far[1],ymax)

Если вы нарисуете прямоугольник с (1,1) и (x, y), вы получите результат, как показано ниже:

enter image description here

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

img2 = img[:y,:x].copy()

Ниже приведен результат:

enter image description here

See, the problem is that you lose some parts of the stitched image.

Ответ 2

Вы можете сделать это с помощью threshold, findContours и boundingRect.

Итак, вот быстрый script делать это с интерфейсом python.

stitched = cv2.imread('stitched.jpg', 0)
(_, mask) = cv2.threshold(stitched, 1.0, 255.0, cv2.THRESH_BINARY);

# findContours destroys input
temp = mask.copy()
(contours, _) = cv2.findContours(temp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# sort contours by largest first (if there are more than one)
contours = sorted(contours, key=lambda contour:len(contour), reverse=True)
roi = cv2.boundingRect(contours[0])

# use the roi to select into the original 'stitched' image
stitched[roi[1]:roi[3], roi[0]:roi[2]]

Заканчивается следующим образом: enter image description here

ПРИМЕЧАНИЕ. Сортировка может не потребоваться с необработанными изображениями, но при использовании сжатого изображения возникают некоторые артефакты сжатия, которые появляются при использовании низкого порога, поэтому я пост-обработал с сортировкой.

Надеюсь, что это поможет!

Ответ 3

Вы можете использовать активные контуры (воздушные шары/змеи) для точного выбора черной области. Демонстрацию можно найти здесь. Активные контуры доступны в OpenCV, проверьте cvSnakeImage.