OpenCV-suppression du bruit dans l'image

j'ai une image ici avec une table.. Dans la colonne de droite, le fond est rempli avec le bruit

Comment détecter les zones de bruit? Je veux seulement appliquer une sorte de filtre sur les pièces avec du bruit parce que j'ai besoin de faire des OCR dessus et n'importe quel type de filtre réduira la reconnaissance globale

Et quel genre de filtre est le meilleur pour supprimer le bruit de fond dans l'image?

comme dit je dois faire OCR sur le image

enter image description here

18
demandé sur clarkk 2017-02-16 14:15:43

9 réponses

j'ai essayé quelques filtres / opérations dans OpenCV et il semble que cela fonctionne assez bien.

Étape 1:Dilater l'image

kernel = np.ones((5, 5), np.uint8)
cv2.dilate(img, kernel, iterations = 1)

Dilated Image

comme vous le voyez, le bruit est parti mais les personnages sont très légers, donc j'ai Érodé l'image.

Etape 2: Éroder l'image

kernel = np.ones((5, 5), np.uint8)
cv2.erode(img, kernel, iterations = 1)

Eroded dilated image

Comme vous pouvez le voir, le bruit a disparu cependant, certains caractères sur les autres colonnes sont cassés. Je recommande d'exécuter ces opérations sur la colonne bruyante seulement. Vous pouvez utiliser HoughLines pour trouver la dernière colonne. Vous pouvez alors extraire cette colonne seulement, exécuter dilation + érosion et la remplacer par la colonne correspondante dans l'image originale. De plus, dilation + erosion est en fait une opération appelée clôture. Ce que vous pouvez appeler directement en utilisant -

cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

comme @Ermlg l'a suggéré, medianBlur avec un noyau de 3 fonctionne aussi merveilleusement.

cv2.medianBlur(img, 3)

Median Blur

Place

comme vous pouvez le voir tous ces filtres fonctionnent mais il est préférable que vous implémentiez ces filtres seulement dans la partie où le bruit est. Pour ce faire, utilisez la commande suivante:

edges = cv2.Canny(img, 50, 150, apertureSize = 3) // img is gray here
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, 1000, 50) // last two arguments are minimum line length and max gap between two lines respectively.
for line in lines: 
    for x1, y1, x2, y2 in line: 
        print x1, y1
// This gives the start coordinates for all the lines. You should take the x value which is between (0.75 * w, w) where w is the width of the entire image. This will give you essentially **(x1, y1) = (1896, 766)**

alors, vous pouvez extraire cette partie seulement comme :

extract = img[y1:h, x1:w] // w, h are width and height of the image

Extracted image

puis, implémentez le filtre (médian ou fermeture) dans cette image. Après avoir enlevé le bruit, vous devez mettre cette image filtrée à la place de la partie floue dans l'image originale. image[y1: h, x1: w] = median

Ceci est simple en C++:

extract.copyTo(img, new Rect(x1, y1, w - x1, h - y1))

résultat Final avec une autre méthode

Final Result Espérons qu'il aide!

9
répondu Rick M. 2017-05-01 14:44:56

ma solution est basée sur le battage pour obtenir l'image résultante en 4 étapes.

  1. Lire image par OpenCV 3.2.0.
  2. Appliquer GaussianBlur() pour lisser l'image surtout la région en couleur grise.
  3. masquer l'image pour changer le texte en blanc et le reste en noir.
  4. inversez l'image masquée en texte noir en blanc.

Le code est Python 2.7. Il peut être modifié à C++ facilement.

import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline 

# read Danish doc image 
img = cv2.imread('./imagesStackoverflow/danish_invoice.png')

# apply GaussianBlur to smooth image
blur = cv2.GaussianBlur(img,(5,3), 1) 

# threshhold gray region to white (255,255, 255) and sets the rest to black(0,0,0)
mask=cv2.inRange(blur,(0,0,0),(150,150,150))

# invert the image to have text black-in-white
res = 255 - mask

plt.figure(1)
plt.subplot(121), plt.imshow(img[:,:,::-1]), plt.title('original') 
plt.subplot(122), plt.imshow(blur, cmap='gray'), plt.title('blurred')
plt.figure(2)
plt.subplot(121), plt.imshow(mask, cmap='gray'), plt.title('masked')
plt.subplot(122), plt.imshow(res, cmap='gray'), plt.title('result')
plt.show()

ce qui suit est le images tracées par le code de référence.

enter image description here

Ici image résultat à 2197 x 3218 pixels.

enter image description here

7
répondu thewaywewere 2017-05-01 16:56:13

Comme je sais que le filtre médian est la meilleure solution pour réduire le bruit. Je vous recommandons d'utiliser le filtre médian 3x3 fenêtre. Voir la fonction cv:: medianBlur ().

mais soyez prudent lorsque vous utilisez une filtration du bruit en même temps que la ROC. Les Its peuvent entraîner une diminution de la précision de la reconnaissance.

je recommande aussi d'essayer d'utiliser une paire de fonctions (cv::erode() et cv::dilate()). Mais je ne suis pas sûr que la meilleure solution sera alors cv:: medianBlur () avec la fenêtre de 3x3.

3
répondu ErmIg 2017-07-07 11:52:18

je dirais flou médian (probablement 5*5 kernel).

si vous prévoyez d'appliquer ROC l'image. Je vous conseille de le suivant:

  1. filtrer l'image à L'aide du filtre médian.
  2. trouver des contours dans l'image filtrée, vous n'obtiendrez que des contours texte (appelez-les F).
  3. trouver les contours de l'image originale (les appeler O).
  4. isoler tous les contours dans O qui ont intersection avec tout contour en F.

solution plus rapide:

  1. trouver les contours de l'image originale.
  2. Filtrer en fonction de la taille.
2
répondu Humam Helfawi 2017-02-16 11:34:09

Résultat:

enter image description here

2
répondu Antonio 2017-05-04 16:11:27

si vous êtes très inquiet de supprimer les pixels qui pourraient nuire à votre détection OCR. Sans ajouter d'artefacts, il faut être aussi pur que possible. Ensuite, vous devez créer un filtre blob. Et supprimez tous les blobs qui sont plus petits que n pixels ou ainsi.

Je ne vais pas écrire de code, mais je sais que cela fonctionne très bien car je l'utilise moi-même, bien que je n'utilise pas openCV (j'ai écrit mon propre multithread blobfilter hors de raisons de vitesse). Et désolé mais je ne peux pas partager mon code ici. Simplement décrire comment faire.

1
répondu user3800527 2017-05-04 14:45:33

si le temps de traitement n'est pas un problème, une méthode très efficace dans ce cas serait de calculer tous les composants connectés noirs, et supprimer ceux plus petits que quelques pixels. Il supprimerait tous les points bruyants (à l'exception de ceux touchant une composante VALIDE), mais préserverait tous les caractères et la structure du document (lignes et ainsi de suite).

La fonction à utiliser serait connectedecomponentwithstats (avant que vous ayez probablement besoin de produire l'image négative, le seuil function THRESH_BINARY_INV fonctionnerait dans ce cas), dessin des rectangles blancs où de petits composants connectés ont été trouvés.

En fait, cette méthode pourrait être utilisée pour rechercher des caractères, défini comme les composantes connexes d'une taille minimale et maximale, et l'aspect ratio dans une plage donnée.

1
répondu Antonio 2017-05-05 23:24:29

j'avais déjà fait face au même problème et obtenu la meilleure solution. Convertir l'image source en niveaux de gris de l'image et appliquer fastNlMeanDenoising fonction et ensuite appliquer seuil.

ce fastNlMeansDenoising(gris,de l'heure d'été,3.0,21,7); seuil (dst,finaldst, 150, 255, THRESH_BINARY);

aussi utiliser peut ajuster le seuil en accordance avec votre image de bruit de fond. par exemple- threshold (dst,finaldst, 200, 255, THRESH_BINARY);

NOTE-Si les lignes de votre colonne ont été supprimées...Vous pouvez prendre un masque de lignes de colonne de l'image source et peut s'appliquer à l'image résultante dénoisée en utilisant des opérations BITWISE comme et, ou, XOR.

1
répondu Amul Mittal 2018-03-09 07:14:28

essayez de battre l'image comme ceci. Assurez-vous que votre src est en échelle de gris. Cette méthode ne retiendra que les pixels dont l'intensité se situe entre 150 et 255.

threshold(src, output, 150, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

vous pourriez vouloir Inverser l'image comme vous essayez de nier les pixels gris. Après l'opération, inversez à nouveau pour obtenir le résultat désiré.

-2
répondu Aliasgar Murtaza 2017-04-20 10:03:26