5

In einer Papierwährung möchte ich überprüfen, ob der Streifen unterbrochen oder durchgezogen ist. Dafür habe ich ein Foto mit dem Hintergrund ein starkes Licht gemacht. Und ich habe die folgenden zwei Bilder, eines eine echte Währung und das andere ein gefälschtes. Ich habe das Bild an der Stelle zugeschnitten, an der der Streifen existiert, und habe die Öffnungs- und Schließrekonstruktion durchgeführt und schließlich die schwarzen Pixel gezählt. Aber das Ergebnis ist nicht so, wie ich es wollte. Irgendeine Hilfe?Papierwährungserkennung durch Bildverarbeitung

Hier sind die Bilder:

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(:)); 

Antwort

15

Hier ist meine eher verpatzten Versuch festzustellen, ob Ihre Banknote gefälscht oder echt ist. Eine Sache, die mir zwischen den Noten aufgefallen ist, ist, dass der dünne Streifen der dünnen Note mehr oder weniger kontinuierlich ist, während der falsche Streifen dünne Linien in dem Streifen fragmentiert hat. Man könnte sagen, dass die falsche Note mehr als eine Zeile in dem dünnen Streifen hat, während die echte Note nur eine Zeile hat. Lassen Sie uns versuchen, unser Bild so zu bekommen, dass wir den Streifen selbst erkennen (wie Sie es auch schon versucht haben) und wir zählen, wie viele Zeilen wir sehen. Wenn wir nur eine Zeile sehen, ist es real, aber wenn wir mehr als eine Zeile sehen, ist es falsch. Ich werde Ihnen zeigen, wie ich das gemacht habe, mit Zwischenbildern dazwischen.

Schritt # 1 - Lesen Sie im Bild (natürlich)

Ich werde direkt auf Ihre Bilder in von Stackoverflow lesen. imread ist ideal für Bilder von Online-URLs zu lesen:

%%//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 

Schritt # 2 - Bild in HSV Zerlege und

Eine Sache analysieren ich bemerkt habe ist, dass die Streifen sehr dunkel sind, während die Banknote überwiegend grün ist in Farbe. Ich habe eine grundlegende Farbbildverarbeitung als Vorverarbeitungsschritt verwendet. Ich verwandelt das Bild in HSV (Hue-Saturation-Value) und an jeder Komponente separat einen Blick nahm:

%% 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'); 

Hier sind, was die Bilder wie folgt aussehen:

enter image description here

enter image description here

In diesem Code Ich zeige jede der Komponenten nebeneinander für den Farbton, die Sättigung und den Wert an. Sie werden etwas sehr Eigenartiges bemerken. Der schwarze dünne Streifen hat eine ziemlich hohe Sättigung, was sinnvoll ist, da Schwarz als eine "Farbe" betrachtet werden kann, die eine reine Sättigung ist (ohne weißes Licht). Die Wertkomponente hat ihren Streifen mit sehr niedrigen Werten, was auch Sinn macht, da Wert die Helligkeit/Intensität der Farbe erfasst.

Schritt # 3 - Schwellen der Sättigung und Wert Ebene ein binäres Bild

Mit den Beobachtungen zu schaffen ich oben gemacht, ich bin zu Schwelle des Bild in der Sättigung und Wert Ebenen suchen gehen. Alle Punkte, die eine kombinierte Sättigung aufweisen, die ziemlich hoch ist, und Werte, die eher niedrig sind, sind Kandidaten, die Teil des schwarzen Streifens sind. Ich werde nur die Streifen selbst ausschneiden, um die Dinge zu erleichtern (wie Sie es bereits getan haben). Beachten Sie, dass die Position der Streifen in jedem Bild unterschiedlich ist, also musste ich mich entsprechend anpassen. Ich extrahierte einfach die richtigen Spalten heraus, während ich die Zeilen und die Slices unverändert ließ.Diese Schwellenwerte für Sättigung und Wert sind eher ad-hoc, also musste ich mit diesen herumspielen, um gute Ergebnisse zu erzielen.

%%//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'); 

Diese sind, was die Bilder wie folgt aussehen:

enter image description here

können Sie sehen, dass die reale Streifen mehr oder weniger mehr Konnektivität als die gefälschte Streifen hat. Lassen Sie uns ein bisschen mehr Verarbeitung tun dies, um aufzuräumen

Schritt # 4 - Sie einige kleinere Schließungen

Wenn Sie einen Blick auf die dünnen schwarzen Streifen der gefälschten zur Kenntnis nehmen, werden Sie sehen, dass jede schwarze Linie ist um ein paar Pixel getrennt, während die echte Note wirklich keine Trennung hat. Sie werden jedoch sehen, dass in dem echten Streifen oben immer noch einige Teile der Linie getrennt sind. Versuchen wir also, die Linie miteinander zu verbinden. Dies ist sicher, denn wenn wir dies auf dem gefälschten Bild tun, sind die Teile des Streifens so weit voneinander entfernt, dass das Schließen keinen Unterschied machen würde, aber es wird uns bei unserer echten Bildanalyse helfen. Als solche schloss ich diese Bilder mit einer 6-Pixel-Linie, die vertikal ist. Hier ist der Code zu tun, dass:

%%//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'); 

Diese sind, was die Bilder wie folgt aussehen:

enter image description here

Schritt # 5 - Abschluss Bereinigung

Sie, dass für jeden der auffallen wird, Bilder, es gibt einige verrauschte Pixel an den Rändern. Daher verwenden wir einen Bereich, der sich durch bwareaopen öffnet. Diese Funktion entfernt Pixelbereiche in einem Schwarzweißbild mit weniger als einem bestimmten Bereich. Ich wähle 15, um die Pixel entlang der Kanten loszuwerden, die nicht zum Streifen gehören. Als solche:

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

Hier ist, was die Bilder wie folgt aussehen:

enter image description here

Schritt # 6 - die Anzahl der schwarzen Linien Graf

Der letzte Schritt besteht darin, einfach die Anzahl der Zählung schwarze Linien in jedem Bild. Wenn es nur 1 gibt, bedeutet dies, dass die Banknote echt ist, während, wenn es mehr als 1 gibt, dies bedeutet, dass die Banknote gefälscht ist. Wir können bwlabel verwenden und den zweiten Parameter verwenden, um zu zählen, wie viele Objekte vorhanden sind. Mit anderen Worten:

%%//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)]); 

Wir erhalten die folgende Ausgabe 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 

Wie Sie die reale Note nur eine Zeile sehen können, hat, während die gefälschte Banknote mehr als eine hat. Sie müssen mit diesem Code spielen, je nachdem, welche Banknote Sie benötigen, um zu funktionieren, aber das ist irgendwo zu starten.


Voll Code

Nur der Vollständigkeit halber hier der vollständige Code ist so können Sie kopieren und einfügen und in MATLAB selbst betreiben.

%%//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)]); 

Bearbeiten - 4. September 2014

Sie kontaktierte mich und wollte wissen, wie die großen schwarzen Streifen zu erkennen, die auf der rechten Seite jeder Note ist. Das ist eigentlich gar nicht so schlecht. Das Bild, das Sie gepostet haben, das ist die andere falsche Note, hat eine andere Größe als die anderen. Daher werde ich dieses Bild so skalieren, dass dieses Bild ungefähr die gleiche Größe hat wie die anderen, die Sie gezeigt haben. Dies ist das Bild, das Sie in den Kommentaren Beiträge geschrieben haben:

Durch auf alle Notizen suchen, schweben sie zwischen der 195. Spalte zu der 215. Spalte. Dies setzt voraus, dass jedes Bild 320 Spalten aufweist. Nun, der Prozess hinter dem, wie ich feststelle, ob die Banknote gefälscht ist, besteht darin, die Gesamtintensität des schwarzen Streifens selbst zu betrachten. Sie werden feststellen, dass die falschen Noten entweder keinen schwarzen Streifen haben oder der Streifen eher stumpf und verblasst ist. Wir können das sicherlich zu unserem Vorteil nutzen. Hier ist eine kurze Liste von dem, was habe ich die schwarzen Streifen zu erkennen:

  • liest in den Bildern und die Größe sie alle denselben Spalten bei Bedarf
  • die 195. bis 215. Spalten Auszug für alle Bilder
  • Konvertieren Sie die Bilder in Graustufen mit rgb2gray
  • Schwellen Sie die Bilder mit etwa Intensität 30. Ich verwendete 30 heuristisch, da dies überwiegend die Intensität war, die ich sah, dass der schwarze Streifen bestand aus. Sie invertieren dann die Bilder, so dass Schwarz weiß wird. Ich brauche den schwarzen Streifen, um für weitere Analysen weiß zu werden. Ich benutze im2bw, um dies zu tun.
  • Ich Bereich öffne das Bild wie ich zuvor, aber Angabe einer größeren Fläche von etwa 100, um sicherzustellen, dass ich alle störenden lauten und isolierten Pixel loswerden.
  • Ich schließe mit einem quadratischen strukturierenden Element von 5 x 5, um sicherzustellen, dass alle nicht verbundenen Regionen, die in der Nähe von größeren Regionen sind, miteinander verbunden werden.
  • Ich zähle dann die Gesamtzahl der Objekte, die übrig sind. Wenn die Anzahl ungleich 1 ist, dann ist es eine falsche Notiz. Wenn es nur 1 ist, dann ist es eine echte Note.

Hier ist der vollständige Code:

%% //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)]); 

Beachten Sie, dass Sie mit diesen Parametern rumspielen müssen werden Ihre Zwecke. Hier sind, was die Zahlen bei jedem Schritt wie folgt aussehen:

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

...und schließlich das Objekt zählen:

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 

Viel Glück!

+0

das perfekt mein Problem gerichtet. Wie wäre es, wenn ich den breiteren Streifen auf der rechten Seite der Notiz identifizieren möchte, da einige falsche Notizen den dünnen Streifen haben und nicht den breiteren Streifen haben. Hier ein Beispiel: http://imgur.com/SVJrwaV – user3472037

+0

@ user3472037 - Befindet sich der breitere Streifen generell im selben Bereich für alle Banknoten? Wenn es so ist, kann ich eine andere Methode vorschlagen, die die Sättigung und den Wert verwendet, wie ich vorher erwähnt habe, aber wir würden nach dem Vorhandensein eines einzelnen Streifens/einer Linie suchen. Dies erleichtert die Arbeit, wenn der Standort mehr oder weniger fest ist. Gib mir Bescheid! – rayryeng

+0

@raryryeng Ja, die breitere Fläche ist für alle Banknoten im gleichen Bereich wie der dünne Streifen. – user3472037

1

Folgendes habe ich versucht. Es ist wichtig, dass Sie in diesem Ansatz ein Schutzband um das Liniensegment herum zulassen, anstatt die Region auf die Breite des Liniensegments zu beschränken.

  • Last der rgb Bild
  • das RGB-Bild zu schließen, so dass dunkler Liniensegmente entfernt oder de-betont, dann diese geschlossene Bild umwandeln in Graustufen (wir nennen diese im1)
  • rgb Bild konvertieren maßstabs grau, dann Kontrast erhöhen (wir nennen diese IM2)
  • nehmen den Unterschied: im1 - IM2
  • die Projektion dieses Differenzbild nehmen. Dies sollte Ihnen ein 1-D-Signal
  • Sie dieses Signal zusätzlich glätten
  • Schwelle es und die Anzahl der Segmente
  • Sie eine höhere Anzahl von Segmenten erhalten für die gestrichelte Linie Bild finden sollten

Im Folgenden sind die Ergebnisse für die gegebenen Beispielbilder:

Eingabebilder:

enter image description hereenter image description here

Difference Bilder:

enter image description hereenter image description here

Projektionen und Segmente:

enter image description here

Und hier ist der Matlab-Code:

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')