2015-10-29 3 views
2

Pour simplifier, j'ai une série de photos prises avec un appareil photo. Cette caméra était derrière un dôme en acrylique et ce dôme a des rayures dessus. Les rayures sont très apparentes sur les photos. Avec opencv, j'essaie de détecter et de supprimer ces rayures. Ma première approche est de multiplier un sous-ensemble des images pour créer un masque, que d'appliquer le masque inpaint. Suis-je sur la bonne voie? Y a-t-il un traitement que je peux faire sur les images avant de les multiplier?Détection (et suppression) des rayures d'un ensemble d'images

enter image description here enter image description here enter image description here enter image description here

EDIT: Voici une image mettant en lumière les rayures enter image description here

+1

Pouvez-vous fournir quelques images par exemple? – Miki

+0

@Miki Images ajoutées! – Goldorak84

+0

Un filtre médian peut être efficace sur les rayures minces. – ChronoTrigger

Répondre

2

Après quelques tests, je suis venu avec un moyen fiable pour éliminer les rayures récurrentes et les taches de poussière sur une ensemble d'images. Tout d'abord, je prends un sous-ensemble de 10 à 15 images, les ouvre, et applique sobel derivatives pour extraire les contours.

 private Image<Gray, byte> GetImageContours(String strImage) 
     { 
      Image<Gray, Byte> img = new Image<Gray, byte>(strImage); 
      Image<Gray, float> gradx = img.Sobel(1, 0, 5); 
      Image<Gray, Byte> gradxconv = gradx.ConvertScale<Byte>(1, 0); 
      Image<Gray, float> grady = img.Sobel(0, 1, 5); 
      Image<Gray, Byte> gradyconv = grady.ConvertScale<Byte>(1, 0); 
      Image<Gray, Byte> imgContours = gradxconv.AddWeighted(gradyconv, 0.5, 0.5, 0); 

      img.Dispose(); 
      gradx.Dispose(); 
      grady.Dispose(); 
      gradxconv.Dispose(); 
      gradyconv.Dispose(); 

      return imgContours; 
     } 

Ensuite, je convertis les images à une profondeur de 16 bits, puis je les multiplie toutes. Cela devrait me donner une image des rayures seulement. Pour créer un masque des rayures, j'érode cette image une fois, puis je la dilate 10 fois. Après cela, je le convertis en noir et blanc en exécutant un TresholdBinary avec une valeur de seuil de 40.

La dernière étape consiste à utiliser la fonction Inpaint sur tout l'ensemble d'images avec le masque de travail.

  Image<Gray, float> _img1 = img1.Convert<Gray, float>(); 
      Image<Gray, float> _img2 = img2.Convert<Gray, float>(); 
      Image<Gray, float> _img3 = img3.Convert<Gray, float>(); 
      Image<Gray, float> _img4 = img4.Convert<Gray, float>(); 
      Image<Gray, float> _img5 = img5.Convert<Gray, float>(); 
      Image<Gray, float> _img6 = img6.Convert<Gray, float>(); 
      Image<Gray, float> _img7 = img7.Convert<Gray, float>(); 
      Image<Gray, float> _img8 = img8.Convert<Gray, float>(); 
      Image<Gray, float> _img9 = img9.Convert<Gray, float>(); 
      Image<Gray, float> _img10 = img10.Convert<Gray, float>(); 
      Image<Gray, float> _img11 = img11.Convert<Gray, float>(); 
      Image<Gray, float> _img12 = img12.Convert<Gray, float>(); 
      Image<Gray, float> imgMask = _img1.Mul(_img2).Mul(_img3).Mul(_img4).Mul(_img5).Mul(_img6).Mul(_img7).Mul(_img8).Mul(_img9).Mul(_img10).Mul(_img11).Mul(_img12).Erode(1); 
      Image<Gray, Byte> imgMask2 = imgMask.Convert<Gray, Byte>(); 
      Image<Gray, Byte> imgMask3 = imgMask2.Dilate(10).ThresholdBinary(new Gray(40), new Gray(255)); 

      //img is one of the original images to remove scratches on 
      ImageViewer viewer3 = new ImageViewer(img.InPaint(imgMask3, 3), "image3"); 
      viewer3.Show(); 

Voici des échantillons d'images prises à chaque étape:

image originale enter image description here

contours de cette image enter image description here

tous les contours multipliés enter image description here

la m ask érodé et dilatée enter image description here

le résultat final enter image description here