2012-05-17 114 views
10

He cosido dos imágenes juntas usando funciones de OpenCV y C++. Ahora estoy enfrentando el problema de que la imagen final contiene una gran parte negra.¿Cómo eliminar la parte negra de la imagen?

La imagen final debe ser un rectángulo que contenga la parte efectiva. Mi imagen es la siguiente:

enter image description here

¿Cómo puedo quitar la sección de negro?

+0

Probablemente se podría utilizar cvFindContours para obtener la extensión de su contenido de la imagen y después recortar a que ... – LiMuBei

+2

mientras que la adición de imágenes en cuestión, muestra el resultado usando 'imwrite' y añádelo. Es mejor que agregar una captura de pantalla, ya que los que responden a su pregunta deben eliminar las regiones no deseadas de la imagen. –

+4

Su espacio de trabajo está ordenado. – wengseng

Respuesta

16

mevatron La respuesta es una de las formas en que se minimiza la cantidad de región negra al tiempo que se conserva la imagen completa.

Otra opción es eliminar la región negra completa en la que también se pierde parte de la imagen, pero el resultado será una imagen rectangular de apariencia ordenada. A continuación está el código de Python.

Aquí, se encuentran tres esquinas principales de la imagen de la siguiente manera:

enter image description here

He marcado esos valores. (1,x2), (x1,1), (x3,y3). Se basa en la suposición de que su imagen comienza desde (1,1).

Código:

Los primeros pasos son los mismos que mevatron 's. Desenfoque la imagen para eliminar el ruido, limite la imagen y luego encuentre los contornos.

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) 

Ahora encuentre el contorno más grande que es su imagen. Es para evitar el ruido en caso de que haya alguno (lo más probable es que no haya ninguno). O puede usar el método 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 

Ahora aproxima el contorno para eliminar los puntos innecesarios en los valores de contorno encontrados, pero conserva todos los valores de las esquinas.

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

Ahora encontramos las esquinas.

Primero, encontramos (x3, y3). Es el punto más alejado. Entonces x3*y3 será muy grande. Así que encontramos productos de todos los pares de puntos y seleccionamos el par con el producto máximo.

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

Siguiente (1, x2). Es el punto donde el primer elemento es uno, luego el segundo elemento es máximo.

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

Siguiente (x1,1). Es el punto donde el segundo elemento es 1, luego el primer elemento es máximo.

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

Ahora nos encontramos con la minimum values in (far.x,xmax) and (far.y, ymax)

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

Si dibuja un rectángulo con (1,1) y (x, y), puede obtener un resultado de la siguiente manera:

enter image description here

Para recortar la imagen para corregir el área rectangular.

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

A continuación se muestra el resultado:

enter image description here

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

+1

: Como estoy más familiarizado con C++ y traté de convertir el código (en python) a C++ pero no pude tener mucho éxito. Si pudiera compartir el mismo código en lenguaje C++, estaría muy agradecido. –

+0

lo siento, no soy bueno en C++. Pero si me dices si tienes alguna duda sobre algún paso en mi método, puedo explicarlo de una manera mucho más simple. –

+0

: He realizado todos los pasos hasta aprox. PDP, pero no sé cómo calcular el producto de los puntos de coordenadas en C y creo que también ha usado un seudo código. ¿Puede decirme cómo puedo calcular el producto de los puntos de coordenadas en C? o dame un enlace donde alguien haya usado tu tipo de método en C.Para referenciar mi imagen después de aplicar el método approxpoly() es [http://i.imgur.com/Qfoyt.jpg?1]. Espero que también tengas el misma imagen de salida después de aplicar approxpolyDp(). –

0

Puede usar contornos activos (globos/serpientes) para seleccionar con precisión la región negra. Se puede encontrar una demostración here. Los contornos activos están disponibles en OpenCV, marque cvSnakeImage.

+0

¿Puede mostrarme cómo implementarlo para eliminar la parte negra? –

8

Puede hacerlo con threshold, findContours y boundingRect.

Entonces, aquí hay una secuencia de comandos rápida haciendo esto con la interfaz de 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]] 

termina pareciéndose a esto: enter image description here

NOTA: clasificación puede no ser necesario con imágenes en bruto, pero el uso de la imagen comprimida causado algunos artefactos de compresión que aparecen cuando se utiliza un umbral bajo, así que es por eso que post-procesé con clasificación.

Espero que ayude!

+0

+1 gran ejemplo de trabajo. – karlphillip

Cuestiones relacionadas