Mejorar la detección del área de texto (OpenCV, Python)

Estoy trabajando en un proyecto que me pide que detecte el área de texto en una imagen. Este es el resultado que logré hasta ahora usando el código a continuación.

Imagen original original

Resultado Resultado

El código es el siguiente:

import cv2 import numpy as np # read and scale down image img = cv2.pyrDown(cv2.imread('C:\\Users\\Work\\Desktop\\test.png', cv2.IMREAD_UNCHANGED)) # threshold image ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY) # find contours and get the external one image, contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # with each contour, draw boundingRect in green # a minAreaRect in red and # a minEnclosingCircle in blue for c in contours: # get the bounding rect x, y, w, h = cv2.boundingRect(c) # draw a green rectangle to visualize the bounding rect cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), thickness=1, lineType=8, shift=0) # get the min area rect #rect = cv2.minAreaRect(c) #box = cv2.boxPoints(rect) # convert all coordinates floating point values to int #box = np.int0(box) # draw a red 'nghien' rectangle #cv2.drawContours(img, [box], 0, (0, 0, 255)) # finally, get the min enclosing circle #(x, y), radius = cv2.minEnclosingCircle(c) # convert all values to int #center = (int(x), int(y)) #radius = int(radius) # and draw the circle in blue #img = cv2.circle(img, center, radius, (255, 0, 0), 2) print(len(contours)) cv2.drawContours(img, contours, -1, (255, 255, 0), 1) cv2.namedWindow('contours', 0) cv2.imshow('contours', img) while(cv2.waitKey()!=ord('q')): continue cv2.destroyAllWindows() 

Como puede ver, esto puede hacer más de lo que necesito. Busque partes comentadas si necesita más.

Por cierto, lo que necesito es enlazar cada área de texto en un solo rectángulo, no cerca de cada carácter que el script está encontrando. Filtre el único número o letra y redondee todo en un solo cuadro.

Por ejemplo, la primera secuencia en un cuadro, la segunda en otro y así sucesivamente.

Busqué un poco y encontré algo sobre el “área del rectángulo del filtro”. No sé si es útil para mi propósito.

También eché un vistazo a algunos de los primeros resultados en Google, pero la mayoría de ellos no funcionan muy bien. Supongo que el código debe ser ajustado un poco, pero soy un novato en el mundo de OpenCV.

Resuelto utilizando el siguiente código.

 import cv2 # Load the image img = cv2.imread('image.png') # convert to grayscale gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # smooth the image to avoid noises gray = cv2.medianBlur(gray,5) # Apply adaptive threshold thresh = cv2.adaptiveThreshold(gray,255,1,1,11,2) thresh_color = cv2.cvtColor(thresh,cv2.COLOR_GRAY2BGR) # apply some dilation and erosion to join the gaps - change iteration to detect more or less area's thresh = cv2.dilate(thresh,None,iterations = 15) thresh = cv2.erode(thresh,None,iterations = 15) # Find the contours image,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) # For each contour, find the bounding rectangle and draw it for cnt in contours: x,y,w,h = cv2.boundingRect(cnt) cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) cv2.rectangle(thresh_color,(x,y),(x+w,y+h),(0,255,0),2) # Finally show the image cv2.imshow('img',img) cv2.imshow('res',thresh_color) cv2.waitKey(0) cv2.destroyAllWindows() 

Los parámetros que deben modificarse para obtener el resultado a continuación son los números de iteraciones en las funciones de erode y dilate . Los valores más bajos crearán más rectangularjs de límite alrededor (casi) cada dígito / carácter.

Resultado

resultado