Saltar al contenido

Cómo recortar una región de pequeños píxeles en una imagen usando OpenCv en Python

El paso a paso o código que verás en este artículo es la resolución más rápida y efectiva que hallamos a esta duda o problema.

Solución:

Está en el camino correcto, aquí hay un enfoque que usa transformaciones morfológicas

  • Convertir imagen a escala de grises y desenfoque gaussiano
  • Umbral de Otsu
  • Realizar operaciones morfológicas
  • Encuentre contornos y filtre usando el área máxima
  • Extraer retorno de la inversión

La idea es conectar la región deseada en un solo contorno y luego filtrar usando el área máxima. De esta manera, podemos tomar la región como una sola pieza. Aquí está el área detectada

Luego, podemos extraer la región con Numpy Slicing

import cv2

image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (9,9), 0)
thresh = cv2.threshold(gray,0,255,cv2.THRESH_OTSU + cv2.THRESH_BINARY)[1]

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
dilate_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
dilate = cv2.dilate(opening, dilate_kernel, iterations=5)

cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)

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]
    break

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('dilate', dilate)
cv2.imshow('image', image)
cv2.imshow('ROI', ROI)
cv2.waitKey(0)

Aquí está mi enfoque usando NumPy sum. Simplemente sume los valores de píxeles a lo largo de los ejes x e y individualmente, configure algunos umbrales para la cantidad mínima de píxeles que describen el área deseada y obtenga los índices de columna y fila adecuados.

Echemos un vistazo al siguiente código:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# Read input image; get shape
img = cv2.imread('images/UKf5Z.jpg', cv2.IMREAD_GRAYSCALE)
w, h = img.shape[0:2]

# Threshold to prevent JPG artifacts
_, img = cv2.threshold(img, 240, 255, cv2.THRESH_BINARY)

# Sum pixels along x and y axis
xSum = np.sum(img / 255, axis=0)
ySum = np.sum(img / 255, axis=1)

# Visualize curves
plt.plot(xSum)
plt.plot(ySum)
plt.show()

# Set up thresholds
xThr = 15
yThr = 15

# Find proper row indices
tmp = np.argwhere(xSum > xThr)
tmp = tmp[np.where((tmp > 20) & (tmp < w - 20))]
x1 = tmp[0]
x2 = tmp[-1]

# Find proper column indices
tmp = np.argwhere(ySum > yThr)
tmp = tmp[np.where((tmp > 20) & (tmp < h - 20))]
y1 = tmp[0]
y2 = tmp[-1]

# Visualize result
out = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.rectangle(out, (x1, y1), (x2, y2), (0, 0, 255), 4)
cv2.imshow('out', out)
cv2.waitKey(0)

Las curvas de las sumas se ven así (solo para fines de visualización):

Curvas

Y, para la visualización, simplemente dibujé un rectángulo rojo descrito por los índices encontrados.

Producción

Como puede ver, excluí manualmente un área de "borde" de 20 píxeles, ya que hay algunos artefactos más grandes. Dependiendo de la ubicación de su área deseada, esto puede ser suficiente. De lo contrario, se debe mantener su enfoque utilizando la apertura morfológica.

¡Espero que ayude!


EDITAR: Como sugiere Mark en su respuesta, usando mean en vez de sum evita adaptaciones con respecto a las diferentes dimensiones de la imagen. Cambiar el código apropiadamente se deja al lector. 🙂

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *