Program steps
- Load the image with Opencv
- Create a copy of the original image to change only the copy and keep the original in memory
- Converts from BGR color space to grayscale as the functions used work with grayscale
- Uses Canny Edges to get format borders
- Find the borders in the image
- Loop each contour found and check if the area is larger than zero, which means it is a geometric shape and not just a line.
- Creates rectangles from the coordinates of the formats found
- Use Grab Cut to remove Background (background)
- Creates a new image cropped from the region of interest of the contour coordinates
Sample Code
import cv2
import numpy as np
import urllib.request
import matplotlib.pyplot as plt
import imutils
def mostrar_imagem_plt(img):
plt.imshow(img)
plt.show()
def mostrar_imagem_cv(img):
cv2.imshow('Imagem', img)
cv2.waitKey(3000)
# Carregar Imagem
resp = urllib.request.urlopen("https://i.stack.imgur.com/qS3i0.jpg")
img = np.asarray(bytearray(resp.read()), dtype="uint8")
img = cv2.imdecode(img, cv2.IMREAD_COLOR)
# img = cv2.imread('C:/Users/usuario/Desktop/teste/qS3i0.png')
copia = img.copy()
# Conversão para escala de Cinza
gray = cv2.cvtColor(copia, cv2.COLOR_BGR2GRAY)
# mostrar_imagem_plt(gray)
mostrar_imagem_cv(np.hstack([copia, cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)]))
# Canny Edges, para obter as bordas
edged = cv2.Canny(gray, 30, 200)
mostrar_imagem_cv(np.hstack([copia, cv2.cvtColor(edged, cv2.COLOR_GRAY2BGR)]))
# Obter contornos, para identificar cada formato geométrico
# verifica se está utilizando OpenCV 2.X
if imutils.is_cv2():
(conts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
# verifica se está utilizando OpenCV 3.X
elif imutils.is_cv3():
(_, conts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
# Constantes do Grab Cut
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
mask = np.zeros(img.shape[:2], np.uint8)
for cnt in conts:
#Informações de cada contorno
area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
if area > 0:
print(area, x, y, w, h)
# Retângulos ao redor de cada formato
cv2.rectangle(copia,(x,y),(x+w,y+h),(0,0,255),3)
mostrar_imagem_cv(copia)
# Grab Cut
rect = (x, y, w, h)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
gc = img.copy() * mask2[:, :, np.newaxis]
mostrar_imagem_cv(gc)
# Região de Interesse a partir do retangulo
roi = gc[y:y + h, x:x + w]
mostrar_imagem_cv(roi)
Results