web-dev-qa-db-fra.com

Comment supprimer les espaces blancs d'une image dans OpenCV?

J'ai l'image suivante qui a du texte et beaucoup d'espace blanc sous le texte. Je voudrais rogner l'espace blanc de sorte qu'il ressemble à la deuxième image.

enter image description here

Image recadrée

enter image description here

Voici ce que j'ai fait

>>> img = cv2.imread("pg13_gau.jpg.png")
>>> gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
>>> edged = cv2.Canny(gray, 30,300)
>>> (img,cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
>>> cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:10]
14
Anthony

Comme beaucoup l'ont fait allusion dans les commentaires, la meilleure façon est d'inverser l'image pour que le texte noir devienne blanc, de trouver tous les points non nuls dans l'image, puis de déterminer quelle serait la zone de délimitation minimale. Vous pouvez utiliser cette boîte englobante pour enfin recadrer votre image. Trouver les contours coûte très cher et n'est pas nécessaire ici - d'autant plus que votre texte est aligné sur l'axe. Vous pouvez utiliser une combinaison de cv2.findNonZero et cv2.boundingRect pour faire ce dont vous avez besoin.

Par conséquent, quelque chose comme ça fonctionnerait:

import numpy as np
import cv2

img = cv2.imread('ws.png') # Read in the image and convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255*(gray < 128).astype(np.uint8) # To invert the text to white
coords = cv2.findNonZero(gray) # Find all non-zero points (text)
x, y, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box
rect = img[y:y+h, x:x+w] # Crop the image - note we do this on the original image
cv2.imshow("Cropped", rect) # Show it
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("rect.png", rect) # Save the image

Le code ci-dessus décrit exactement ce dont j'ai parlé au début. Nous lisons l'image, mais nous la convertissons également en niveaux de gris car votre image est en couleur pour une raison quelconque. La partie délicate est la troisième ligne de code où je seuil en dessous de l'intensité de 128 afin que le texte sombre devienne blanc. Cela produit cependant une image binaire, donc je convertis en uint8, puis redimensionne par 255. Cela inverse essentiellement le texte.

Ensuite, étant donné cette image, nous trouvons toutes les coordonnées non nulles avec cv2.findNonZero et nous avons finalement mis cela dans cv2.boundingRect qui vous donnera le coin supérieur gauche du cadre de sélection ainsi que la largeur et la hauteur . Nous pouvons enfin l'utiliser pour recadrer l'image. Notez que nous le faisons sur l'image d'origine et non sur l'image inversée. Nous utilisons simplement l'indexation du tableau NumPy pour faire le recadrage pour nous.

Enfin, nous montrons l'image pour montrer qu'elle fonctionne et nous l'enregistrons sur le disque.


Je reçois maintenant cette image:

enter image description here


Pour la deuxième image, une bonne chose à faire est de supprimer une partie de la bordure droite et de la bordure inférieure. Nous pouvons le faire en recadrant l'image en premier. Ensuite, cette image contient de très petits pixels bruyants. Je recommanderais de faire une ouverture morphologique avec un très petit noyau, puis de refaire la logique dont nous avons parlé plus haut.

Par conséquent:

import numpy as np
import cv2

img = cv2.imread('pg13_gau_preview.png') # Read in the image and convert to grayscale
img = img[:-20,:-20] # Perform pre-cropping
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = 255*(gray < 128).astype(np.uint8) # To invert the text to white
gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, np.ones((2, 2), dtype=np.uint8)) # Perform noise filtering
coords = cv2.findNonZero(gray) # Find all non-zero points (text)
x, y, w, h = cv2.boundingRect(coords) # Find minimum spanning bounding box
rect = img[y:y+h, x:x+w] # Crop the image - note we do this on the original image
cv2.imshow("Cropped", rect) # Show it
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite("rect.png", rect) # Save the image

Remarque: l'image de sortie a été supprimée en raison de la confidentialité