Corrections de taches sur vieux négatifs avec dt et opencv

Bonjour,
Pour ceux et celles qui aiment « bidouiller » un peu de code :wink:
inspiré de :
https://github.com/Tschucker/Python-Automatic-Sensor-Dust-Removal/blob/main/ocv_dust_inpainting_example/ocv_sensor_dust_inpainting.ipynb

photo originale traitée avec docteur néga dt :

création d’un masque avec dt à base de masque paramétrique seuil des détails et coloriser en noir les zone blanches à ne pas corriger:

Code Python sur ces 2 images:

[code]#!/usr/bin/env python3

‹  ›’
inspiré de
https://github.com/Tschucker/Python-Automatic-Sensor-Dust-Removal/blob/main/ocv_dust_inpainting_example/ocv_sensor_dust_inpainting.ipynb
@author: coelb
‹  ›’

import numpy as np
import cv2

sourcename=« im.png »
maskname = « mask.png »

image = cv2.imread(sourcename, cv2.IMREAD_UNCHANGED)

luminance

select = np.array([[0.114, 0.587, 0.299 ]])
image16gray = cv2.transform(image, select)
#-------------------------- traitement du masque 8 bits
mask8 = cv2.imread(maskname)
#cv2.imwrite(‹ sourcegray.png ›, image16gray)
maskgray = cv2.transform(mask8, select)
#cv2.imwrite(‹ maskgray.png ›, maskgray)
#--------------------seuillage entre 2 valeurs 8 bits à ajuster
global_thresh = cv2.threshold(maskgray,185,240,cv2.THRESH_BINARY)[1]
cv2.imwrite(‹ global_threshold.png ›, global_thresh)
#-----------Filter

grossisement des zones de corrections à ajuster

KERNEL = np.ones((10,10), dtype=int)*10
mask_filt = cv2.filter2D(global_thresh,-1 ,KERNEL)
cv2.imwrite(‹ filter.png ›, mask_filt)

#-----------------------------corrections image

rayon à ajuster

radius = 10
flags = cv2.INPAINT_NS # cv2.INPAINT_NS ou cv2.INPAINT_TELEA
cimg_inpaint = cv2.inpaint(image16gray, mask_filt, radius, flags=flags)
cv2.imwrite(‹ auto_dust_inpainting.png ›, cimg_inpaint)

[/code]

Photo dépoussiérée :

Avec quelques 10 retouches supplémentaires dans dt pour peaufiner. (peux mieux faire)

Cordialement

PS: je n’arrive pas à faire marcher Gimp resynthetizer sur ma machine alors…

Je trouve ça très intéressant, merci Corbert.
Pour les capteurs bien tachés ça peut vraiment aider à gagner du temps.

J’ai aussi déniché de vieilles plaques et des négatifs chez mes parents et, quand j’en aurai le temps je chercherai à les scanner et les « restaurer » numériquement car malheureusement elles sont globalement pas très en forme…
Je ne manquerai pas de tester cette solution !

Je serais preneur de détails sur cette manip… :shy:

Hello,
Le but du masque est de faire apparaître les défauts (poussières, points blancs) avec une luminance supérieures au contenu utile de l’image, j’ai utilisé un clone de l’image à corriger en essayant de faire apparaître en blanc les défauts. Comme je suis bordélique et que je compresse l’historique je ne peux envoyer les xmp sur cet exemple, j’ai fais plusieurs modifs après le post. La clé est un masque paramétrique en n’utilisant que le réglage « seuil des détails » sur coloriser par exemple avec du blanc (sat = o, clarté max). Sur un négatifs les fréquences hautes sont souvent réduites.

Après une autre instance de coloriser( en noir) peut permettre de « descendre » les zones blanches non voulue qui pourrait être prise en compte pour la corrections.

Opencv travaille par défaut sur 8 bits, la corrections peut s’effectuer en couleurs sur 8 bits ou sur monocanal sur 16 bits, le bout de code donné marche sur 16 bits (negatif NB),
Les images sont exporter en png dans dt.

Bon, c’est un peu bidouille expérimentale, si tu as une photo qui t’interesse, je suis partant pour essayer :wink:

Cordialement

Hello,
Pour compléter un lien vers un traitement dt d’un négatif année 1950 : standardistes des P&T avant « l’automatique » ( automatique qu’on espère pour les taches dans dt :stuck_out_tongue: )
https://drive.google.com/drive/folders/1V909NR_QvLJc8-Zxu2rQR8bANQ2bMR65?usp=sharing
fichier raw (arw) avec les xmp de l’image à corriger et du masque,
Les .png exportés par dt renommés en image et mask : l’image en rec2020 linéaire 16 bits pour tester, le mask en srvb)
Le tiff généré par le code dust.py avec son traitement sur dt et son export en jpeg.
Le petit code dust.py a été adapté pour gérer la couleur et le NB en 16 bits. Il fonctionne dans le même répertoire que les png (à améliorer)

Pour le fun,
Cordialement

Merci pour le lien. Je vais regarder et voir avec quelques-uns de mes scans de négatifs.

Bonsoir,

@JPG54 Si tu peux me faire un retour quand tu pourras.

Je viens d’essayer sur la photo sous marine du post https://forums.darktable.fr/showthread.php?tid=6553

C’est la constellation de taches mais on arrive à en éliminer quand même pas mal. il faut de toutes façon compléter manuellement.


Cordialement.

Bien sûr, je reviendrai quand j’aurais pris en main et fait quelques tests sur mes négatifs.

Ca tombe bien ta méthode de correction des taches, je viens de recevoir le duplicateur de films argentiques JJC :
https://fr.aliexpress.com/item/1005003788099019.html?spm=a2g0o.order_list.order_list_main.17.21ef5e5bwJc10E&gatewayAdapt=glo2fra
l’éclairage n’est pas compris et je l’attends, il est coincé en douanes. Je te ferai un retour.

hello,
tu n’as pas déjà plein de trucs pour les negatifs? :cool:
https://forums.darktable.fr/showthread.php?tid=4539
cdlt

Bon j’ai essayé cette bidouille ce WE, que nenni ça ne fonctionne pas chez moi.
Je ne dois pas avoir l’opencv qui va bien, 4.8.0-5 pour moi.
Pô grave de son coté mon Gimp Resynthesize bien. :wink:

Ceci dit, bien vu, le contournement de " Coloriser " pour mettre en évidence les hautes luminances de l’image.

M’enfin cela montre aussi qu’un petit module de dépoussiérage serait le bien venu dans dt.

@ jpg54
Je récupère fin de mois dans les archives d’une asso, dont je faisais partie il y a… bien longtemps,
près de 500 de mes anciennes photos, diapos faites avec deux Olympus OM1.
Et je suis toujours comme toi à l’affût de la bonne solution, pour les négas comme les diapos.
Ça a l’air pas mal cet adaptateur JJC, donne ton avis sur le fil déjà ouvert sur le sujet.

Oui, j’ai essayé plusieurs choses pour dupliquer les photos. Ce que je déconseille absolument, c’est le duplicateur Sumikon Objectiv-Aufsatz et des duplicateurs qui contiennent une loupe pour pourvoir être utilisé sur les objectifs non-macro : je pense que celui de Nikon, la loupe est de bonne qualité.
Après le rétro-éclairage avec une tablette est très bien, mais est longue à mise en route et le changement de films ou de diapos, par contre, elle n’est pas limitée pour les tailles de films argentiques. De plus, il faut découper le film par vues pour le passer dans l’adaptateur.
Le DigitaLAZE+ est pas mal pour les films en bandes même entière. Pour les diapos et les films 6x6, c’est un peu plus compliqué de les positionner.
Le scanner à plat avec rétroéclairage, c’est un certain prix pour un bon et vraiment onéreux pour un qui permet des films jusqu’au A4. En plus, la durée de digitalisation est relativement lente en 3600 DPI et il faut absolument l’ordinateur en fonction pour le logiciel. En plus, je ne suis vraiment pas fan du logiciel sous Linux qui est payant.
Aurélien n’avait prêté son digitaliseur PluTec qui va très bien, mais juste limité au 24x36 et aussi avec un logiciel pour le driver.
Pour le JJC Film Digitalize Film, première impression :
pas de loupe et il faut l’utiliser sur un objectif macro (pour moi, avec le Leica 45mm f:2.8 macro en µ4/3), j’ai essayé avec le Leica 12-60mm f:2.8-4 : reproduction couvre un peu moins que le moitié du capteur sans bonnette (bonnette acromatique de bonne qualité) ;
utilisation devant une fenêtre bien éclairée : c’est vraiment confortable et rapide, à 200 ISO à 5.6 vitesse > 1/10 (condition idéale pour le maxi de qualité en µ4/3) ;
le JJC Led Light Set (https://www.amazon.com/Negative-Scanning-Adjustable-Negatives-Converter/dp/B09NKVJ7Y5?th=1 ) permet de rétro-éclairé les films avec avec 9 niveaux d’éclairage, mais aussi de permettre de prendre en photo les films et diapos soit en main levée ou sur pied ;
avec le système complet, après avoir fait les réglages, il ne reste plus qu’à déclencher et passer de vue à vue.
Une petite remarque, sur AliExpress, il montre le système complet et en tout petit qu’il n’y a pas le rétro-éclairage et Amazon au même prix et même moins cher en fonction des promos AliExpress.
[hr]
Je vais l’essayer un peu ces jours-ci.
[hr]
Il y a eu beaucoup de bricolages proposés sur ForumLumix.fr : j’aime bien celui qui utilise un ancien projecteur de diapos (dommage, je n’ai pas récupéré le mien à un déménagement) et aussi qui utilise le flash pour rétro-éclairé le film.

@ jpg54
Ça au moins c’est du retour d’expérience. :shy:
Pour l’instant j’en reste à ma tablette Kaiser, certes le setup est un peu long à mettre en place mais comme c’est pour numériser en masse c’est relatif.
Macro pour le cailloux, of course, mais mon 1/2 macro ( XF 60 F2.4 ) avec une petite bague allonge et le tour est joué.

@ Cobert
J’aimerais bien quand même essayer ce petit bout de code python.
J’ai une erreur dès l’entrée, dès que cv2.imread est appelé… inconnu au bataillon !
En dehors d’OpenCV (qu’elle version) y a-t-il d’autres pré-requis

Je viens d’installer sur mon Gx8 avec le Leica 45mm f:2.8 macro 1x1 :

J’avais aussi testé les scanner films/diapos, ceux de Lidl et Aldi sont à éviter, pas terrible à 5 Mp et supérieur c’est de l’interpolation.
J’ai eu le Rollei DF-S 310 SE ; le Scan Reflecta et le Rollei DiaFilmScanner, ils sont bien et rapide, ils enregistrent les scans sur une carte SD avec les négatifs convertis et ne nécessite pas l’ordinateur. Par contre on a que des JPeg.
Le scanner que m’a prêté Aurélien et un Pacific : la marque de Reflecta au States !

Bonsoir,
Moi aussi je suis à la tablette Kaiser car j’avais des 4x4 et autres formats non 24-36. Pour les négatifs gondolés, pas évident, mais j’en ai pas non plus des masses.
@Jacotux
Pour le bout de code, les noms sont pour l’instant codés en dur dans le code python : image.png et mask.png qui sont les sorties de dt en png 16 bits renommées, ça marche tel quel si le code est au même endroit que les images. On peut modifier directement dans le code les chemins et noms.Peut-être est ce le pb ?
Sinon je suis en opencv 4.8.0
Je teste une autre méthode pour faire le masque à partir de l’image avec opencv (pour les photos où il n’y a pas de confusion entre taches et contenu utile)
et j’ai trouvé une meilleure méthode pour faire le masque noir et blanc dans dt avec 2 colorieurs que je teste aussi.
Si c’est concluant, j’améliorerai le bout de code avec arguments et test d’erreurs :cool:
Si vous avez des exemples de raw à partager, pour varier un peu, je peux tester :wink:

Voilà un resto plein de taches !
Cordialement.

Pour moi, c’est OpenCV 4.7.-1.8 sous OpenSuse Tumbelweed.
[hr]
J’ai aussi une erreur à l’exécution :

Traceback (most recent call last): File "dust.py", line 9, in <module> import numpy as np ImportError: No module named numpy

@ Cobert
Suis aussi en 4.8.0, donc ce n’est pas ça.
J’avais bien ouvert une console dans le dossier de mes photos tests.
Et vu qu’il me fallait modifier le nom de mes images.
C’est peut-être là que j’ai fait une boulette… une erreur de frappe arrive vite.
Il était tard quand j’ai essayé ( ou plutôt tôt ), je vais donc m’y remettre.

Oui la préparation dans dt initialement doit bien aider dust.py
C’était déjà « sioux » l’astuce du module « Coloriser », utiliser OpenCV et l’intégrer serait le grand luxe.

Pour les négas et diapos empoussiérés je pense qu’il n’y aura pas trop de pb, les poussières sont faciles à mettre en évidence.
Par contre, traiter par exemple la prise de vue subaquatique de Clo, entre les bulles, les particules en suspension, je crain s que ce soit plus complexe.

@JPG54
Il faut avoir les 2 modules numpy et opencv python d’installés ( pip3 install numpy)

Toujours la même erreur après l’exécution de ta commande.
J’avais déjà numpy installé :

@JPG54
bizarre, et si tu lances python en ligne de commande et fait import numpy :


cà donne quoi ?

cdlt