5

In una valuta cartacea, voglio controllare che la striscia sia rotta o piena. Per questo ho scattato una foto con lo sfondo di una luce forte. E ho ottenuto le seguenti due immagini, una una valuta originale e l'altra falsa. Ho ritagliato l'immagine nella posizione in cui la striscia esiste e ho fatto la ricostruzione di apertura-chiusura, e infine per contare i pixel neri. Ma il risultato non è come volevo. Qualsiasi aiuto?Riconoscimento valuta carta tramite elaborazione immagini

Ecco le immagini:

enter image description here enter image description here

%Code for the thine strip 
clear all; 
close all; 
I = imread('IMG_4267.jpg'); 
imageSize = size(I); 
croppedImage = imcrop(I,[300 0 30 570]); 
gray=rgb2gray(croppedImage); 
se1 = strel('square',2); 
I1e = imerode(gray, se1); 
I1e = imreconstruct(I1e, gray); 
I1b = imdilate(I1e, se1); 
I1c = imreconstruct(imcomplement(I1b), imcomplement(I1e)); 
I1d = imcomplement(I1c); 
Edge2=edge(I1d,'canny'); 
BW1 = im2bw(Edge2); 
nBlack = sum(BW1(:)); 

risposta

15

Ecco il mio tentativo piuttosto maldestro a determinare se la vostra banconota è falso o reale. Una cosa che ho notato tra le note è che la nota reale ha la sua striscia sottile più o meno continua mentre la striscia finta ha delle linee sottili frammentate nella striscia. Si potrebbe dire che la nota falsa ha più di una riga nella striscia sottile mentre la nota reale ha solo una riga. Proviamo ad ottenere la nostra immagine in modo tale da rilevare la striscia stessa (come hai anche provato) e contiamo quante linee vediamo. Se vediamo solo una riga, è reale, ma se vediamo più di una riga è falsa. Ti guiderò attraverso come l'ho fatto con immagini intermedie in mezzo.

Passo # 1 - Leggere nell'immagine (ovviamente)

ho intenzione di leggere direttamente le immagini in da StackOverflow. imread è grande per la lettura di immagini da URL online:

%%//Read in image 
clear all; 
close all; 
Ireal = imread('http://i.stack.imgur.com/SqbnIm.jpg'); %//Real 
Ifake = imread('http://i.stack.imgur.com/2U3DEm.jpg'); %//Fake 

Passo # 2 - Scomporre immagine in HSV e analizzare

Una cosa che ho notato è che le strisce sono molto scuri, mentre la banconota è prevalentemente verde a colori Ho usato alcune immagini base per l'elaborazione delle immagini come fase di pre-elaborazione. Ho trasformato l'immagine in HSV (Hue-Saturation-Value) e ha preso uno sguardo a ogni componente separatamente:

%% Pre-analysis 
hsvImageReal = rgb2hsv(Ireal); 
hsvImageFake = rgb2hsv(Ifake); 
figure; 
imshow([hsvImageReal(:,:,1) hsvImageReal(:,:,2) hsvImageReal(:,:,3)]); 
title('Real'); 
figure; 
imshow([hsvImageFake(:,:,1) hsvImageFake(:,:,2) hsvImageFake(:,:,3)]); 
title('Fake'); 

Ecco quello che le immagini assomigliano:

enter image description here

enter image description here

In questo codice , Sto visualizzando ciascuno dei componenti l'uno accanto all'altro per la tonalità, la saturazione e il valore rispettivamente. Noterai qualcosa di molto particolare. La striscia nera sottile ha una saturazione abbastanza elevata, il che ha senso in quanto il nero può essere considerato un "colore" che è pura saturazione (privo di luce bianca). Il componente del valore ha la sua striscia con valori molto bassi, il che ha anche senso quando il valore cattura la luminosità/intensità del colore.

Passo # 3 - Soglia la saturazione e il valore piani per creare un'immagine binaria

con le osservazioni che ho fatto in precedenza, ho intenzione di soglia l'immagine guardando gli aerei di saturazione e di valore. Qualsiasi punto che abbia una saturazione combinata piuttosto elevata e valori piuttosto bassi sono candidati che fanno parte della striscia nera. Ho intenzione di ritagliare solo le strisce da sole per rendere le cose più facili (come hai già fatto anche tu). Prendi nota del fatto che la posizione delle strisce in ogni immagine è diversa, quindi mi sono dovuto adeguare di conseguenza. Ho semplicemente estratto le colonne giuste, lasciando le righe e le sezioni uguali.Queste soglie di saturazione e valore sono piuttosto ad-hoc, quindi ho dovuto giocare con queste per ottenere buoni risultati.

%%//Initial segmentation 
croppedImageReal = hsvImageReal(:,90:95,:); 
croppedImageFake = hsvImageFake(:,93:98,:); 
satThresh = 0.4; 
valThresh = 0.3; 
BWImageReal = (croppedImageReal(:,:,2) > satThresh & croppedImageReal(:,:,3) < valThresh); 
figure; 
subplot(1,2,1); 
imshow(BWImageReal); 
title('Real'); 
BWImageFake = (croppedImageFake(:,:,2) > satThresh & croppedImageFake(:,:,3) < valThresh); 
subplot(1,2,2); 
imshow(BWImageFake); 
title('Fake'); 

questi sono ciò che le immagini assomigliano:

enter image description here

Si può vedere che il vero striscia più o meno ha più la connettività rispetto alla striscia di falso. Facciamo un po 'di più di elaborazione per pulire questo

Passo # 4 - Fare qualche chiusure minori

Se si dà un'occhiata alla sottile striscia nera della nota falso, vedrete che ogni linea nera è separati da alcuni pixel mentre la nota reale non ha alcuna separazione. Tuttavia, vedrai che nella striscia reale sopra, ci sono ancora alcune parti della linea che sono disconnesse. Come tale, proviamo a collegare la linea insieme. Questo è sicuro perché se dovessimo farlo sull'immagine falsa, le parti della striscia sono così distanti che la chiusura non dovrebbe fare la differenza, ma aiuterà nella nostra analisi delle immagini reali. Come tale, ho chiuso queste immagini con una linea di 6 pixel che è verticale. Ecco il codice per farlo:

%%//Post-process 
se = strel('line', 6, 90); 
BWImageCloseReal = imclose(BWImageReal, se); 
BWImageCloseFake = imclose(BWImageFake, se); 
figure; 
subplot(1,2,1); 
imshow(BWImageCloseReal); 
title('Real'); 
subplot(1,2,2); 
imshow(BWImageCloseFake); 
title('Fake'); 

questi sono ciò che le immagini assomigliano:

enter image description here

Passo # 5 - pulizia finale

Si noterà che per ciascuno dei immagini, ci sono alcuni pixel rumorosi sui bordi. Come tale, usiamo un'area che si apre attraverso bwareaopen. Questa funzione rimuove le aree dei pixel in un'immagine in bianco e nero con meno di una determinata area. Vado a scegliere 15 per eliminare i pixel lungo i bordi che non appartengono alla striscia. In quanto tale:

%%//Area open the image 
figure; 
areaopenReal = bwareaopen(BWImageCloseReal, 15); 
imshow(areaopenReal); 
title('Real'); 
figure; 
areaopenFake = bwareaopen(BWImageCloseFake, 15); 
imshow(areaopenFake); 
title('Fake'); 

Ecco quello che le immagini assomigliano:

enter image description here

Passo # 6 - Contare il numero di linee nere

L'ultimo passo è quello di contare semplicemente il numero di linee nere in ogni immagine. Se c'è solo 1, questo indica che la banconota è reale, mentre se c'è più di 1, questo indica che la banconota è falsa. Possiamo usare bwlabel e usare il secondo parametro per contare quanti oggetti ci sono. In altre parole:

%%//Count how many objects there are 
[~,countReal] = bwlabel(areaopenReal); 
[~,countFake] = bwlabel(areaopenFake); 
disp(['The total number of black lines for the real note is: ' num2str(countReal)]); 
disp(['The total number of black lines for the fake note is: ' num2str(countFake)]); 

Abbiamo ottenere il seguente output in MATLAB:

The total number of black lines for the real note is: 1 
The total number of black lines for the fake note is: 4 

Come si può vedere, la vera nota ha una sola linea, mentre la nota falsa ha più di una. Dovrai giocare con questo codice a seconda di quale banconota devi far funzionare, ma questo è un punto da cui iniziare.


codice completa

Solo per completezza, ecco il codice completo in modo da poter copiare e incollare ed eseguire in MATLAB te stesso.

%%//Read in image 
clear all; 
close all; 
Ireal = imread('http://i.stack.imgur.com/SqbnIm.jpg'); % Real 
Ifake = imread('http://i.stack.imgur.com/2U3DEm.jpg'); % Fake 

%%//Pre-analysis 
hsvImageReal = rgb2hsv(Ireal); 
hsvImageFake = rgb2hsv(Ifake); 
figure; 
imshow([hsvImageReal(:,:,1) hsvImageReal(:,:,2) hsvImageReal(:,:,3)]); 
title('Real'); 
figure; 
imshow([hsvImageFake(:,:,1) hsvImageFake(:,:,2) hsvImageFake(:,:,3)]); 
title('Fake'); 

%%//Initial segmentation 
croppedImageReal = hsvImageReal(:,90:95,:); 
croppedImageFake = hsvImageFake(:,93:98,:); 
satThresh = 0.4; 
valThresh = 0.3; 
BWImageReal = (croppedImageReal(:,:,2) > satThresh & croppedImageReal(:,:,3) < valThresh); 
figure; 
subplot(1,2,1); 
imshow(BWImageReal); 
title('Real'); 
BWImageFake = (croppedImageFake(:,:,2) > satThresh & croppedImageFake(:,:,3) < valThresh); 
subplot(1,2,2); 
imshow(BWImageFake); 
title('Fake'); 

%%//Post-process 
se = strel('line', 6, 90); 
BWImageCloseReal = imclose(BWImageReal, se); 
BWImageCloseFake = imclose(BWImageFake, se); 
figure; 
subplot(1,2,1); 
imshow(BWImageCloseReal); 
title('Real'); 
subplot(1,2,2); 
imshow(BWImageCloseFake); 
title('Fake'); 

%%//Area open the image 
figure; 
areaopenReal = bwareaopen(BWImageCloseReal, 15); 
subplot(1,2,1); 
imshow(areaopenReal); 
title('Real'); 
subplot(1,2,2); 
areaopenFake = bwareaopen(BWImageCloseFake, 15); 
imshow(areaopenFake); 
title('Fake'); 

%%//Count how many objects there are 
[~,countReal] = bwlabel(areaopenReal); 
[~,countFake] = bwlabel(areaopenFake); 
disp(['The total number of black lines for the real note is: ' num2str(countReal)]); 
disp(['The total number of black lines for the fake note is: ' num2str(countFake)]); 

Edit - 4 Settembre 2014

Lei mi ha contattato e voleva sapere come rilevare la grande striscia nera che si trova a destra di ogni nota. Questo non è poi così male da fare. L'immagine che hai postato è l'altra nota falsa di dimensioni diverse rispetto alle altre. In quanto tale, ridimensionerò questa immagine in modo che questa immagine abbia all'incirca le stesse dimensioni delle altre che hai mostrato. Questa è l'immagine che hai postato nei commenti:

Osservando tutte le note, che oscillano fra la colonna 195 ° alla colonna 215i. Questo presuppone che ogni immagine abbia 320 colonne. Ora, il processo alla base del modo in cui rilevo se la banconota è falsa è guardando l'intensità complessiva della striscia nera stessa. Noterai che le note false non hanno una striscia nera, o la striscia è piuttosto opaca e sbiadita. Possiamo certamente usarlo a nostro vantaggio. Ecco una breve lista di quello che ho fatto per rilevare la striscia nera:

  • Leggi nelle immagini e ridimensionarle per tutte le stesse colonne, quando necessario
  • Estrarre il 195 ° alle colonne 215 ° per tutte le immagini
  • Converti le immagini in scala di grigi usando rgb2gray
  • Soglia le immagini utilizzando il livello di intensità 30. Ho usato 30 euristicamente perché era principalmente l'intensità che ho visto che consisteva nella striscia nera. Quindi inverti le immagini in modo che il nero diventi bianco. Ho bisogno che la striscia nera diventi bianca per ulteriori analisi. Io uso im2bw per fare questo.
  • L'area I apre l'immagine come prima, ma specifica un'area più ampia di circa 100 per garantire di eliminare eventuali pixel spuri rumorosi e isolati.
  • Faccio una chiusura utilizzando un elemento di struttura quadrata di 5 x 5 per garantire che tutte le regioni disconnesse che si trovano in prossimità di regioni più grandi siano collegate tra loro.
  • Conto quindi il numero totale di oggetti rimasti. Se il conteggio è diverso da 1, allora è una nota falsa. Se è solo 1, allora è una nota reale.

Ecco il codice completo:

%% //Read in images 
clear all; 
close all; 
Ireal = imread('http://i.stack.imgur.com/SqbnIm.jpg'); % Real 
Ifake = imread('http://i.stack.imgur.com/2U3DEm.jpg'); % Fake 
Ifake2 = imread('http://i.imgur.com/SVJrwaV.jpg'); % Fake #2 
% //Resize so that we have the same dimensions as the other images 
Ifake2 = imresize(Ifake2, [160 320], 'bilinear'); 

%% //Extract the black strips for each image 
blackStripReal = Ireal(:,195:215,:); 
blackStripFake = Ifake(:,195:215,:); 
blackStripFake2 = Ifake2(:,195:215,:); 

figure(1); 
subplot(1,3,1); 
imshow(blackStripReal); 
title('Real'); 
subplot(1,3,2); 
imshow(blackStripFake); 
title('Fake'); 
subplot(1,3,3); 
imshow(blackStripFake2); 
title('Fake #2'); 

%% //Convert into grayscale then threshold 
blackStripReal = rgb2gray(blackStripReal); 
blackStripFake = rgb2gray(blackStripFake); 
blackStripFake2 = rgb2gray(blackStripFake2); 

figure(2); 
subplot(1,3,1); 
imshow(blackStripReal); 
title('Real'); 
subplot(1,3,2); 
imshow(blackStripFake); 
title('Fake'); 
subplot(1,3,3); 
imshow(blackStripFake2); 
title('Fake #2'); 

%% //Threshold using about intensity 30 
blackStripRealBW = ~im2bw(blackStripReal, 30/255); 
blackStripFakeBW = ~im2bw(blackStripFake, 30/255); 
blackStripFake2BW = ~im2bw(blackStripFake2, 30/255); 

figure(3); 
subplot(1,3,1); 
imshow(blackStripRealBW); 
title('Real'); 
subplot(1,3,2); 
imshow(blackStripFakeBW); 
title('Fake'); 
subplot(1,3,3); 
imshow(blackStripFake2BW); 
title('Fake #2'); 

%% //Area open the image 
figure(4); 
areaopenReal = bwareaopen(blackStripRealBW, 100); 
subplot(1,3,1); 
imshow(areaopenReal); 
title('Real'); 
subplot(1,3,2); 
areaopenFake = bwareaopen(blackStripFakeBW, 100); 
imshow(areaopenFake); 
title('Fake'); 
subplot(1,3,3); 
areaopenFake2 = bwareaopen(blackStripFake2BW, 100); 
imshow(areaopenFake2); 
title('Fake #2'); 

%% //Post-process 
se = strel('square', 5); 
BWImageCloseReal = imclose(areaopenReal, se); 
BWImageCloseFake = imclose(areaopenFake, se); 
BWImageCloseFake2 = imclose(areaopenFake2, se); 
figure(5); 
subplot(1,3,1); 
imshow(BWImageCloseReal); 
title('Real'); 
subplot(1,3,2); 
imshow(BWImageCloseFake); 
title('Fake'); 
subplot(1,3,3); 
imshow(BWImageCloseFake2); 
title('Fake #2'); 

%% //Count the total number of objects in this strip 
[~,countReal] = bwlabel(BWImageCloseReal); 
[~,countFake] = bwlabel(BWImageCloseFake); 
[~,countFake2] = bwlabel(BWImageCloseFake2); 
disp(['The total number of black lines for the real note is: ' num2str(countReal)]); 
disp(['The total number of black lines for the fake note is: ' num2str(countFake)]); 
disp(['The total number of black lines for the second fake note is: ' num2str(countFake2)]); 

Tenete a mente che dovrete giocare con questi parametri in base alle proprie finalità. Ecco quali sono le figure assomigliano ad ogni passo:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

...e, infine, contare l'oggetto:

The total number of black lines for the real note is: 1 
The total number of black lines for the fake note is: 2 
The total number of black lines for the second fake note is: 0 

Buona fortuna!

+0

che ha affrontato perfettamente il mio problema. Che ne dici se voglio identificare la striscia più larga nella parte destra della nota, come alcune note false hanno la striscia sottile e non hanno la striscia più larga. Ecco un esempio: http://imgur.com/SVJrwaV – user3472037

+0

@ user3472037 - La striscia più larga è generalmente nella stessa area per tutte le banconote? Se lo è, posso suggerire un altro metodo usando la saturazione e il valore come ho detto prima, ma dovremmo cercare la presenza di una singola striscia/linea. Ciò faciliterà il lavoro se la posizione è più o meno fissa. Fammi sapere! – rayryeng

+0

@raryryeng Sì, l'area più ampia si trova nella stessa area per tutte le banconote a differenza della striscia sottile. – user3472037

1

Ecco cosa ho provato. È importante consentire alcune bande di guardia attorno al segmento di linea in questo approccio piuttosto che limitare la regione alla larghezza del segmento di linea.

  • carico dell'immagine rgb
  • chiudere l'immagine RGB in modo che i segmenti scuri vengono rimossi o de-enfatizzato, quindi convertire questa immagine chiuso in scala di grigi (che chiameremo questa im1)
  • convertire un'immagine RGB in scala di grigi, quindi il contrasto migliorare (che chiameremo questo IM2)
  • prendere la differenza: IM1 - IM2
  • prendere la proiezione di questa immagine differenza. Questo dovrebbe dare un segnale 1-D
  • è possibile inoltre smussare questo segnale
  • soglia e trovare il numero di segmenti
  • si dovrebbe ottenere un maggior numero di segmenti per l'immagine spezzata

di seguito sono riportati i risultati per le immagini del campione indicata:

immagini in ingresso:

enter image description hereenter image description here

immagini Difference:

enter image description hereenter image description here

proiezioni e segmenti:

enter image description here

Ed ecco il codice Matlab:

clear all; 
close all; 

imt = imread('t.jpg'); 
imf = imread('f.jpg'); 
% convert to gray scale 
grt = rgb2gray(imt); 
grf = rgb2gray(imf); 
% contrast enhance the gray image to emphasize dark lines in lighter background 
grt = imadjust(grt); 
grf = imadjust(grf); 
% close rgb. choose a larger k. idea is to remove the dark line 
k = 7; 
se = ones(k); 
imtcl = imclose(imt, se); 
imfcl = imclose(imf, se); 
% convert closed image to gray scale 
grtcl = rgb2gray(imtcl); 
grfcl = rgb2gray(imfcl); 
% take the difference (closed-gray-scale - contrast-enhanced-gray-scale) 
difft = grtcl - grt; 
difff = grfcl - grf; 
% take the projection of the difference 
pt = sum(difft'); 
pf = sum(difff'); 
% smooth the projection 
ptfilt = conv(pt, ones(1, k)/k, 'same'); 
pffilt = conv(pf, ones(1, k)/k, 'same'); 
% threshold (multiplication by max element is just for visualization) 
tht = (pt > graythresh(pt))*max(pt); 
thf = (pf > graythresh(pf))*max(pf); 
% get the number of segments. we should get more segments for the broken line (nt < nf) 
[lblt, nt] = bwlabel(tht); 
[lblf, nf] = bwlabel(thf); 

figure, 
subplot(2, 1, 1), imshow(difft'), title('difference image for solid line') 
subplot(2, 1, 2), imshow(difff'), title('difference image for broken line') 

figure, 
subplot(2, 1, 1), plot(1:length(pt), pt, 1:length(pt), ptfilt, 1:length(pt), tht), 
title('solid line image'), 
legend('projection', 'smoothed', 'thresholded', 'location', 'eastoutside') 
subplot(2, 1, 2), plot(1:length(pf), pf, 1:length(pf), pffilt, 1:length(pf), thf), 
title('broken line image'), 
legend('projection', 'smoothed', 'thresholded', 'location', 'eastoutside')