web-dev-qa-db-fra.com

Détecter les rayures sur l'image avec beaucoup de bruit

J'ai du mal à détecter les rayures sur ces images. En fait, il est très facile à voir par les yeux humains. Cependant, lors de l'application de certains algorithmes, il y a beaucoup de bruit et je n'ai pas pu extraire le scratch uniquement.

Voici ces images: enter image description here

enter image description here

À l'heure actuelle, j'ai essayé certains types de filtres (lissage, moyenne, médiane, filtre gaussien ou détecteur Sobel Edge) pour effacer le bruit et détecter les rayures, mais ils n'aident pas beaucoup. Pourriez-vous suggérer une idée? Quelques outils ou algorithmes que je devrais considérer?

20
anhnha

Ceci est mon implémentation pour la détection de défauts, c'est une approche très simple mais efficace, j'ai implémenté ce code dans MATLAB, mais il n'y a aucune difficulté à le porter sur n'importe quelle langue car il utilise des opérations de traitement d'image de base.

clc

clear all

close all

  1. Lisez les images et sous-échantillonnez-les (pour un calcul rapide) par un facteur de 2.

im1 = imresize(imread('scratch.jpg'),0.5);

Scratch 1enter image description here

  1. Convertissez-les en échelle de gris.

gray = rgb2gray(im);

GrayImageenter image description here

  1. Appliquez un filtre gaussien de taille 15 X 15.

gSize = 15;

gray = imfilter(gray,fspecial('gaussian',[gSize,gSize],gSize/2),'replicate');

enter image description hereenter image description here

  1. Trouver la magnitude du gradient des images à l'aide du masque Sobel.

[~,~,mg,~] = ImageFeatures.Gradients(gray);

enter image description hereenter image description here

  1. Seuil Amplitude du gradient avec un seuil de 30 centiles de la valeur maximale.

`mgBw = mg> 0,3 * max (mg (:));

enter image description hereenter image description here

  1. Appliquer l'opération morpholgique Fermeture de l'image binaire par un masque de disque de 3 X 3.

mgBw = imclose(mgBw,strel('disk',1));

enter image description hereenter image description here

  1. Appliquer l'analyse des particules (CCL).

mgBw = bwareaopen(mgBw,500);

enter image description hereenter image description here

  1. Fermez à nouveau l'image pour joindre les lignes.

mgBw = imclose(mgBw,strel('disk',2));

enter image description hereenter image description here

  1. Remplissez les trous dans l'image.

mgBw = imfill(mgBw,'holes');

enter image description hereenter image description here

  1. Annotations finales:

enter image description hereenter image description here

Essayez la procédure ci-dessus sur vos images, j'espère que cela fonctionnera

Merci

Les valeurs pour le masque gaussien sont données ci-dessous.

         0.00253790859361804,0.00284879446220838,0.00314141610419987,0.00340305543986557,0.00362152753952273,0.00378611472031542,0.00388843599983945,0.00392315394879368,0.00388843599983945,0.00378611472031542,0.00362152753952273,0.00340305543986557,0.00314141610419987,0.00284879446220838,0.00253790859361804;
         0.00284879446220838,0.00319776287779517,0.00352622975612324,0.00381991909245893,0.00406515334132644,0.00424990193722614,0.00436475725361032,0.00440372804277458,0.00436475725361032,0.00424990193722614,0.00406515334132644,0.00381991909245893,0.00352622975612324,0.00319776287779517,0.00284879446220838;
         0.00314141610419987,0.00352622975612324,0.00388843599983945,0.00421229243210782,0.00448271658130972,0.00468644212981339,0.00481309512122034,0.00485606890058492,0.00481309512122034,0.00468644212981339,0.00448271658130972,0.00421229243210782,0.00388843599983945,0.00352622975612324,0.00314141610419987;
         0.00340305543986557,0.00381991909245893,0.00421229243210782,0.00456312191696750,0.00485606890058492,0.00507676215263394,0.00521396370030743,0.00526051663974220,0.00521396370030743,0.00507676215263394,0.00485606890058492,0.00456312191696750,0.00421229243210782,0.00381991909245893,0.00340305543986557;
         0.00362152753952273,0.00406515334132644,0.00448271658130972,0.00485606890058492,0.00516782273108746,0.00540268422664802,0.00554869395001131,0.00559823553262373,0.00554869395001131,0.00540268422664802,0.00516782273108746,0.00485606890058492,0.00448271658130972,0.00406515334132644,0.00362152753952273;
         0.00378611472031542,0.00424990193722614,0.00468644212981339,0.00507676215263394,0.00540268422664802,0.00564821944786971,0.00580086485975791,0.00585265795345929,0.00580086485975791,0.00564821944786971,0.00540268422664802,0.00507676215263394,0.00468644212981339,0.00424990193722614,0.00378611472031542;
         0.00388843599983945,0.00436475725361032,0.00481309512122034,0.00521396370030743,0.00554869395001131,0.00580086485975791,0.00595763557555571,0.00601082839853353,0.00595763557555571,0.00580086485975791,0.00554869395001131,0.00521396370030743,0.00481309512122034,0.00436475725361032,0.00388843599983945;
         0.00392315394879368,0.00440372804277458,0.00485606890058492,0.00526051663974220,0.00559823553262373,0.00585265795345929,0.00601082839853353,0.00606449615428972,0.00601082839853353,0.00585265795345929,0.00559823553262373,0.00526051663974220,0.00485606890058492,0.00440372804277458,0.00392315394879368;
         0.00388843599983945,0.00436475725361032,0.00481309512122034,0.00521396370030743,0.00554869395001131,0.00580086485975791,0.00595763557555571,0.00601082839853353,0.00595763557555571,0.00580086485975791,0.00554869395001131,0.00521396370030743,0.00481309512122034,0.00436475725361032,0.00388843599983945;
         0.00378611472031542,0.00424990193722614,0.00468644212981339,0.00507676215263394,0.00540268422664802,0.00564821944786971,0.00580086485975791,0.00585265795345929,0.00580086485975791,0.00564821944786971,0.00540268422664802,0.00507676215263394,0.00468644212981339,0.00424990193722614,0.00378611472031542;
         0.00362152753952273,0.00406515334132644,0.00448271658130972,0.00485606890058492,0.00516782273108746,0.00540268422664802,0.00554869395001131,0.00559823553262373,0.00554869395001131,0.00540268422664802,0.00516782273108746,0.00485606890058492,0.00448271658130972,0.00406515334132644,0.00362152753952273;
         0.00340305543986557,0.00381991909245893,0.00421229243210782,0.00456312191696750,0.00485606890058492,0.00507676215263394,0.00521396370030743,0.00526051663974220,0.00521396370030743,0.00507676215263394,0.00485606890058492,0.00456312191696750,0.00421229243210782,0.00381991909245893,0.00340305543986557;
         0.00314141610419987,0.00352622975612324,0.00388843599983945,0.00421229243210782,0.00448271658130972,0.00468644212981339,0.00481309512122034,0.00485606890058492,0.00481309512122034,0.00468644212981339,0.00448271658130972,0.00421229243210782,0.00388843599983945,0.00352622975612324,0.00314141610419987;
         0.00284879446220838,0.00319776287779517,0.00352622975612324,0.00381991909245893,0.00406515334132644,0.00424990193722614,0.00436475725361032,0.00440372804277458,0.00436475725361032,0.00424990193722614,0.00406515334132644,0.00381991909245893,0.00352622975612324,0.00319776287779517,0.00284879446220838;
         0.00253790859361804,0.00284879446220838,0.00314141610419987,0.00340305543986557,0.00362152753952273,0.00378611472031542,0.00388843599983945,0.00392315394879368,0.00388843599983945,0.00378611472031542,0.00362152753952273,0.00340305543986557,0.00314141610419987,0.00284879446220838,0.00253790859361804;

Masque Sobel:

 1, 2, 1;
 0, 0, 0;
-1,-2, 1;

et

 1, 0,-1;
 2, 0,-2;
 1, 0,-1;

Code d'amplitude du gradient Sobel (ImageFeatures.Gradient):

function [gx,gy,mag,phi] = Gradients(gray)
    gray = double(gray);
    horzmask = fspecial('sobel');
  %  vertmask = horzmask';

    gx = imfilter(gray,horzmask,'replicate');
    gy = imfilter(gray,horzmask','replicate');

    phi = (atan2((gy),(gx)));

    mag = mat2gray(sqrt(gx.^2+gy.^2));
end
9
Ankit Dixit

J'ai essayé la procédure suivante pour la détection. La sortie semble modérée, mais j'ai quand même pensé au partage.

  • sous-échantillonner l'image couleur.
  • appliquer un flou médian avec différentes tailles de fenêtre, puis prendre la différence absolue: je fais cela pour améliorer les marques de rayures et en même temps obtenir un aplatissement de l'éclairage. Vous trouverez ci-dessous les différences d'images obtenues de cette façon. sample difference imagesample difference image 2

  • utilisez la segmentation d'arrière-plan/premier plan basée sur le mélange gaussien pour segmenter les marques de rayure dans l'image de différence. L'idée est que nous pouvons extraire m x n fenêtres de cette image et les former. Comme les rayures ne occupent pas une grande zone dans l'image de différence, nous pouvons penser que l'arrière-plan appris devrait se rapprocher de la zone en dehors des rayures. Cette méthode a mieux fonctionné pour les deux images de différence que d'appliquer un seuil à l'image de différence. Cette méthode n'a pas bien fonctionné lorsque j'ai alimenté directement l'image sous-échantillonnée. Je pense que cela est dû à la nature non uniforme des valeurs de couleur des pixels dans les régions. J'ai donc utilisé l'image de différence d'éclairage aplatie. Voici les images segmentées. Cette procédure est lente car elle vérifie chaque fenêtre m x n possible dans l'image. segmentedsegmented 2

  • utilisez la transformée de Hough probabiliste pour détecter les lignes dans l'image segmentée. En utilisant la densité de lignes dans les régions ou en utilisant un filtrage morphologique pour les lignes, je pense qu'il est possible d'arriver à une estimation raisonnable de l'endroit où se trouvent les rayures. hough loneshough lines 2

Voici le code

code de segmentation en arrière-plan:

Mat threshold_mog(Mat& im, Size window)
{
    BackgroundSubtractorMOG2 bgModel;
    Mat fgMask;
    Mat output = Mat::ones(im.rows, im.cols, CV_8U);

    for (int r = 0; r < im.rows - window.height; r++)
    {
        for (int c = 0; c < im.cols - window.width; c++)
        {
            bgModel.operator()(im(Rect(c, r, window.width, window.height)), fgMask);
        }
    }

    for (int r = 0; r < im.rows - window.height; r++)
    {
        for (int c = 0; c < im.cols - window.width; c++)
        {
            Mat region = im(Rect(c, r, window.width, window.height));
        bgModel.operator()(region, fgMask, 0);
            fgMask.copyTo(output(Rect(c, r, window.width, window.height)));
        }
    }

    return output;
}

principale:

Mat rgb = imread("scratch_2.png.jpg");

pyrDown(rgb, rgb);

Mat med, med2, dif, bw;

medianBlur(rgb, med, 3);
medianBlur(rgb, med2, 21);

absdiff(med2, med, dif);

bw = threshold_mog(dif, Size(15, 15));

Mat dst = bw.clone();
vector<Vec4i> lines;
HoughLinesP(dst, lines, 1, CV_PI/180, 8, 10, 20);
for( size_t i = 0; i < lines.size(); i++ )
{
    Vec4i l = lines[i];
    line(rgb, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 1, CV_AA);
}
2
dhanushka

Je suis la procédure d'Ankit Dixit pour détecter les rayures et obtenir des problèmes. Tout d'abord, parce que j'utilise C++ au lieu de MATLAB, je voudrais donc vérifier s'il y a un malentendu sur l'algorithme.

Pour l'instant, je n'utilise que le filtre gaussien 5x5 car il est disponible. Quelle est la raison pour laquelle vous avez choisi la taille de fenêtre 15x15 au lieu de 5x5? Deuxièmement, mon image après le masque Sobel ne semble pas aussi bonne que la vôtre. Y a-t-il des spéciaux/différents dans Sobel de Matlab?

Voici les images: Gris: http://s15.postimg.org/q8s5y2sjf/Gray_Image.png Filtre gaussien 5x5: http://s1.postimg.org/80r9x20tr/Gaussian_Filter_5x5. png Faire Sobel: http://s21.postimg.org/vxwyju58n/Sobel_Image.png

0
anhnha