Skip to content

Algoritmo robusto per rilevare l'illuminazione non uniforme nelle immagini [Detection Only Needed]

Abbiamo trovato la soluzione a questa preoccupazione, almeno così pensiamo. Se continui con le domande puoi scriverlo nella sezione commenti, ti risponderemo senza esitazione

Soluzione:

Perché non rimuovere l'effetto lampo dalle immagini?

Per esempio:

enter image description here

Se vogliamo leggere con pytesseract l'uscita sarà ' nf'

  • Ma se rimuoviamo il fulmine:

import cv2
import pytesseract

img = cv2.imread('img2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
smooth = cv2.GaussianBlur(gray, (95, 95), 0)
division = cv2.divide(gray, smooth, scale=192)

enter image description here

  • e leggiamo con il parametro pytesseract, una parte dell'output sarà:
.
.
.
Dosage & use
See package insert for compicic
information,

Instruction:
Keep all medicines out of the re.
Read the instructions carefully

Storage:
Store at temperature below 30°C.
Protect from Heat, light & moisture. BATCH NO. : 014C003
MFG. DATE - 03-2019

—— EXP. DATE : 03-2021

GENIX Distributed
AS Exclusi i :
genx PHARMA PRIVATE LIMITED Cevoka Pv 2 A ‘<
» 45-B, Kore ci
Karachi-75190, | Pakisier al Pei yaa fans
www.genixpharma.com
  • Ripetere per l'ultima immagine:

enter image description here

  • E leggere con il tasto pytesseract, una parte dell'output sarà:
.
.
.
Dosage & use
See package insert for complete prescribing
information. Rx Only

Instruction:
Keep all medicines out of the reach of children.
Read the instructions carefully before using.

Storage:

Store at temperature below 30°C. 5

Protect from Neat, light & moisture. BATCH NO, : 0140003
MFG. DATE : 03-2019
EXP. DATE : 03-2021

Manufactured by:

GENI N Exclusively Distributed by:
GENIX PHARMA PRIVATE LIMITED Ceyoka (Pvt) Ltd.

44, 45-B, Korangi Creek Road, 55, Negombe Road,
Karachi-75190, Pakistan. Peliyagoda, Snianka,

www. genixpharma.com

Aggiornamento

È possibile trovare la parte illuminata utilizzando erode e dilatation .

Risultato:

enter image description here

Codice:


import cv2
import imutils
import numpy as np
from skimage import measure
from imutils import contours

img = cv2.imread('img2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (95, 95), 0)
thresh = cv2.threshold(blurred, 200, 255, cv2.THRESH_BINARY)[1]
thresh = cv2.erode(thresh, None, iterations=2)
thresh = cv2.dilate(thresh, None, iterations=4)
labels = measure.label(thresh, neighbors=8, background=0)
mask = np.zeros(thresh.shape, dtype="uint8")
for label in np.unique(labels):
    if label == 0:
        continue
    labelMask = np.zeros(thresh.shape, dtype="uint8")
    labelMask[labels == label] = 255
    numPixels = cv2.countNonZero(labelMask)
    if numPixels > 300:
        mask = cv2.add(mask, labelMask)

    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
                            cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cnts = contours.sort_contours(cnts)[0]
    for (i, c) in enumerate(cnts):
        (x, y, w, h) = cv2.boundingRect(c)
        ((cX, cY), radius) = cv2.minEnclosingCircle(c)
        cv2.circle(img, (int(cX), int(cY)), int(radius),
                   (0, 0, 255), 3)
        cv2.putText(img, "#{}".format(i + 1), (x, y - 15),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
    cv2.imshow("Image", img)
    cv2.waitKey(0)

Tuttavia, ho effettuato il test solo con la seconda immagine. Potrebbe essere necessario modificare i parametri per le altre immagini.

Ecco una soluzione rapida in ImageMagick. Ma può essere facilmente implementata in Python/OpenCV come mostrato più avanti.

Utilizzare la normalizzazione delle divisioni.

  • Leggere l'input
  • Convertire facoltativamente in scala di grigi
  • Copia l'immagine e la sfoca
  • Dividere l'immagine sfocata per l'originale
  • Salvare i risultati

Ingresso:

enter image description here

enter image description here

enter image description here

convert 8W0bp.jpg ( +clone -blur 0x13 ) +swap -compose divide -composite x1.png

convert ob87W.jpg ( +clone -blur 0x13 ) +swap -compose divide -composite x2.png

convert HLJuA.jpg ( +clone -blur 0x13 ) +swap -compose divide -composite x3.png

Risultati:

enter image description here

enter image description here

enter image description here

In Python/OpenCV:

import cv2
import numpy as np
import skimage.filters as filters

# read the image
img = cv2.imread('8W0bp.jpg')
#img = cv2.imread('ob87W.jpg')
#img = cv2.imread('HLJuA.jpg')

# convert to gray
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# blur
smooth = cv2.GaussianBlur(gray, (33,33), 0)

# divide gray by morphology image
division = cv2.divide(gray, smooth, scale=255)

# sharpen using unsharp masking
sharp = filters.unsharp_mask(division, radius=1.5, amount=2.5, multichannel=False, preserve_range=False)
sharp = (255*sharp).clip(0,255).astype(np.uint8)

# save results
cv2.imwrite('8W0bp_division.jpg',division)
cv2.imwrite('8W0bp_division_sharp.jpg',sharp)
#cv2.imwrite('ob87W_division.jpg',division)
#cv2.imwrite('ob87W_division_sharp.jpg',sharp)
#cv2.imwrite('HLJuA_division.jpg',division)
#cv2.imwrite('HLJuA_division_sharp.jpg',sharp)

# show results
cv2.imshow('smooth', smooth)  
cv2.imshow('division', division)  
cv2.imshow('sharp', sharp)  
cv2.waitKey(0)
cv2.destroyAllWindows()

Risultati:

enter image description here

enter image description here

enter image description here

Suggerisco di usare il trucco della divisione per separare il testo dallo sfondo e poi calcolare le statistiche solo sullo sfondo. Dopo aver impostato alcune soglie ragionevoli, è facile creare un classificatore per l'illuminazione.

def get_image_stats(img_path, lbl):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (25, 25), 0)
    no_text = gray * ((gray/blurred)>0.99)                     # select background only
    no_text[no_text<10] = no_text[no_text>20].mean()           # convert black pixels to mean value
    no_bright = no_text.copy()
    no_bright[no_bright>220] = no_bright[no_bright<220].mean() # disregard bright pixels

    print(lbl)
    std = no_bright.std()
    print('STD:', std)
    bright = (no_text>220).sum()
    print('Brigth pixels:', bright)
    plt.figure()
    plt.hist(no_text.reshape(-1,1), 25)
    plt.title(lbl)

    if std>25:
        print("!!! Detected uneven illumination")
    if no_text.mean()<200 and bright>8000:
        print("!!! Detected glare")

Il risultato è:

 good_img
STD: 11.264569863071165
Brigth pixels: 58

 glare_img
STD: 15.00149131296984
Brigth pixels: 15122
!!! Detected glare

 uneven_img
STD: 57.99510339944441
Brigth pixels: 688
!!! Detected uneven illumination

enter image description here

Ora analizziamo gli istogrammi e applichiamo un po' di buon senso. Ci aspettiamo che lo sfondo sia uniforme e abbia una bassa varianza, come nel caso di "good_img". Se ha un'alta varianza, allora la sua deviazione standard è alta ed è il caso di una luminosità non uniforme. Nell'immagine inferiore si possono notare 3 picchi (più piccoli) che sono responsabili delle 3 diverse aree illuminate. Il picco più grande al centro è il risultato dell'impostazione di tutti i pixel neri al valore medio. Credo che si possano definire le immagini con STD superiore a 25 come casi di "illuminazione non uniforme".

È facile individuare un'elevata quantità di pixel luminosi in presenza di riflessi (vedere l'immagine a destra). L'immagine abbagliata appare come una buona immagine, a parte il punto caldo. L'impostazione della soglia di pixel luminosi a qualcosa come 8000 (1,5% della dimensione totale dell'immagine) dovrebbe essere buona per rilevare tali immagini. È possibile che lo sfondo sia molto luminoso ovunque, quindi se la media di no_text è superiore a 200, allora è il caso e non è necessario rilevare i punti caldi.

Valutazioni e recensioni

Ci farebbe molto piacere se potessi dare visibilità a questo post se risolvesse il tuo problema.



Utilizzate il nostro motore di ricerca

Ricerca
Generic filters

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.