基于matlab的人民幣的自動識別
姓
名
學
號
院
系
信息科學與工程學院
專
業
年
級
指導老師
摘要
本文通過分析第五版人民幣的特征,利用紙幣中央數字的特征提取和識別的方法,通過matlab軟件實現對第五版人民幣的100元、50元和20元的識別。
關鍵詞:第五套人民幣
邊緣檢測和提取
中央數字特征
前言:科技在不斷進步,曾經的很多手工勞動如今都被先進的機械和電子設備代替。曾經人們交話費、存款、買東西都必須到營業廳或者商場去辦理手續,通過客戶和服務人員之間的業務交流實現服務的實施和體驗。如今,自動繳費機、存取款一體機和自動售貨機出現在了我們的生活中。這些先進的設備中最重要的一門技術就是:紙幣識別技術。當我們將鈔票投入繳費機或者存款機時,機器必定會首先識別用戶投入的是面額為多少的紙幣,之后再進行真偽辨別、數據寫入等功能。目前已經有很多的識別技術諸如圖像匹配法識別,神經網絡識別、尺寸識別、紙幣內部熒光物質識別等等。本小組提出使用matlab軟件,利用軟件對圖像處理的超強能力,在保證識別準確率的前提下對100元、50元和20元的人民幣進行快速有效的識別。
正文
一.背景介紹
二.Matlab函數介紹
1.Imread
函數imread用于讀取圖片文件中的數據。
調用格式:
A
=
imread(filename,fmt)
[X,map]
=
imread(filename,fmt)
[...]
=
imread(filename)
2.Imshow
imshow是matlab中顯示圖像的函數。
調用格式:
imshow(BW):顯示一張二值圖像BW
imshow(RGB):顯示一張真彩色圖像RGB
imshow(X,map):用指定調色板來顯示圖像
3.im2bw
matlab中DIP工具箱函數im2bw使用閾值(threshold)變換法把灰度圖像(grayscale
image)轉換成二值圖像。一般意義上是指只有純黑(0)、純白(255)兩種顏色的圖像。
當然,也可以是其他任意兩種顏色的組合。所謂二值圖像,一般意義上是指只有純黑(0)、純白(255)兩種顏色的圖像。
當然,也可以是其他任意兩種顏色的組合。
調用格式:
BW
=
im2bw(I,level)
BW
=
im2bw(X,map,level)
BW
=
im2bw(RGB,level)
其中level就是設置閾值的。level取值范圍[0,1]。
4.Imfill
該函數用于填充圖像區域和“空洞”。
調用格式:
BW2
=
imfill(BW)
這種格式將一張二值圖像顯示在屏幕上,允許用戶使用鼠標在圖像上點幾個點,這幾個點圍成的區域即要填充的區域。要以這種交互方式操作,BW必須是一個二維的圖像。用戶可以通過按Backspace鍵或者Delete鍵來取消之前選擇的區域;通過shift+鼠標左鍵單擊或者鼠標右鍵單擊或雙擊可以確定選擇區域。
[BW2,locations]
=
imfill(BW)
這種方式,將返回用戶的取樣點索引值。注意這里索引值不是選取樣點的坐標。
BW2
=
imfill(BW,locations)
這種格式允許用戶編程時指定選取樣點的索引。locations是個多維數組時,數組每一行指定一個區域。
BW2
=
imfill(BW,'holes')
填充二值圖像中的空洞區域。
如,黑色的背景上有個白色的圓圈。
則這個圓圈內區域將被填充。
I2
=
imfill(I)
這種調用格式將填充灰度圖像中所有的空洞區域。
BW2
=
imfill(BW,locations,conn)
5.Bwperim
用于查找二值圖像的邊緣。
調用格式:
BW2
=
bwperim(BW1)
BW2
=
bwperim(BW1,conn)
BW2
=
bwperim(BW1,conn)
表示從輸入圖像BW1中返回只包括對象邊緣像素點的圖像。
6.Mode
眾數函數,用于計算一組數據中的眾數。
眾數,簡單的說,就是一組數據中占比例最多的那個數。
調用格式:
mode(x)
7.medfilt2
中值濾波函數.調用格式:
medfilt2(A,[m
n])
8.Logical
用于判斷參數是否為邏輯值,如果檢驗內容為邏輯值,將返回TRUE(1),否則返回FALSE(0)。
調用格式:
Logical(value)
9.Find
用來對原始數據中的某個字符串進行定位,以確定其位置。
10.edge
調用格式:
BW=edge(I)
采用灰度或一個二值化圖像I作為它的輸入,并返回一個與I相同大小的二值化圖像BW,在函數檢測到邊緣的地方為1,其他地方為0.BW=edge(I,’sobel’)
自動選擇閾值用sobel算子進行邊緣檢測。
算子還有roberts算子,prewitt算子,log算子等等。
三.紙幣識別流程圖
讀入待檢測圖片
得出結果
進行圖像邊緣檢測提取和邊緣剪切
中央數字部分識別
提取中央數字部分
四.流程各部分詳細說明
1.讀入待檢測圖片
Im=imread(‘100.jpg’);
figure(1)
imshow(Im);
讀入一張有黑色背景的100元人民幣圖片。然后使用imshow函數進行圖片查看。
2.進行圖像邊緣檢測提取
邊緣檢測共有兩種方法,一種是使用edge函數進行邊緣檢測;另一種是二值化+圖像填充+提取邊緣的方法。
使用edge函數進行邊緣檢測,選擇Sobel算子。
F=edge(I2,'sobel');%sobel算子邊緣檢測
figure(2)
imshow(F)
如圖,sobel算子邊緣檢測后的圖像。達到需要的效果。但是由于內部白色紋路較多,為了不影響邊緣截取,故選擇第二種方法:二值化+圖像填充+提取邊緣。
首先對圖像進行二值化處理,然后使用imfill函數,調用“hole”格式,對圖像中的空洞進行填充。然后調用bwperim函數,對二值圖像進行邊緣檢測。下面是檢測的過程和結果。
3.邊緣剪切
得到了二值化的邊緣圖像后,需要對邊緣進行剪切,以切掉背景圖案,只留下鈔票圖案,便于按比例分割圖片。
我們采用mode函數,對邊緣位置確定。首先,將二值圖讀入矩陣,生成m行n列的矩陣。然后一行一行進行檢測,遇到白色的區域(值為1)時,就將白色區域所處的列位置記入數組。當檢測完畢后,使用mode函數對數組進行檢測,數組中數字出現的最多的即是邊緣的位置。關鍵循環如下:
for
i=1:m
for
j=1:n
if
F(i,j)~=0%0代表黑色,如果F(i,j)不是黑色(則是圖像區域)
k=k+1;
left(k)=j;
for
j1=n:-1:j
if
F(i,j1)~=0
l=l+1;
right(l)=j1
break
end
end
break
end
end
end
如圖為剪切后的效果灰度圖。
4.提取中央數字部分
百元鈔票左邊到中央數字1的距離大概占整個長度的0.25,右邊是0.5,上邊是0.275,下邊是0.5。20元和50元的類似。所以使用:
FFv2=jianqie(0.275*m:0.50*m,0.254*n:0.5*n)
就可以得到中央數字的圖片。
5.中央部分識別
中央部分識別分兩步:1.區分百元和50、20元;2.區分50元和20元。
區分百元的方法很簡單。因為無論是百元還是50元還是20元,截取的部分大小都是固定的,而100是3位數,故而所占圖片的比例肯定最大。經手算得100元的中央數字大約占超過截取道德圖像的80%。所以由此可以判斷出待檢圖像是不是100元。以下是關鍵程序:
Ty_100=logical(sum(FFv2_bw)<=(mt2-2));
Ty_100_l=find((Ty_100==1));%
rat_100=(Ty_100_l(end)-Ty_100_l(1))/nt2;
if
rat_100>=0.8%
val_mid=100;%val_mid為檢測結果
Else
……
如果待檢圖片不是100元圖片,則進行下一步,50元和20元的區分。
因為50和20均為2位數,故無法通過所占比例進行區分。只能通過數字的某些特征進行區分。我們只需要區分開5和2即可。
如圖所示5和2的細節圖。取5和2的靠左的一小部分進行比較(紅框圈的),數字5后兩根藍線之間的距離小于上面兩根藍線的距離,而2恰恰相反。于是可以得出結果。
關鍵程序如下:
[hang_m,hang_n]=size(hang);
hang_new=round(sum(hang,2)/hang_n);
hang_black=hang_new(2)-hang_new(1);%第一個黑點和第二個白點之間的距離
hang_white=hang_new(3)-hang_new(2);%第二個白點和第二個黑點之間的距離
if
hang_black>=hang_white
val_mid
=
50;
else
val_mid
=
20;
end
end
五.程序運行結果
結果顯示正確。
六.遇到的問題
1.關于背景復雜度的問題。
由于邊緣檢測和提取的算法不完善導致識別程序具有局限性。體現在如下兩方面:
(1)
過于復雜的背景無法正常識別;
因為背景如果過于復雜,二值化后會導致很多復雜的背景變成連續的線條。當這些線條比較長的時候,邊緣檢測程序就會將這段線條識別為邊緣,因為眾數計算的時候這個位置同樣滿足。所以系統會認為此處就是邊緣,但事實上只是背景中的一些二值化的線條。故而導致剪切邊緣無法正確實現,進而影響到后面的中央分割和識別。
如圖,是復雜背景的邊緣檢測結果。
第一幅圖的原圖為黑色背景中有隨機繪制的幾條長曲線,第二幅圖的原圖是背景為實際生活中的建筑物照片。兩幅圖的輪廓均無法正常提取。第一幅從曲線部分開始進行提取,位置錯誤。第二幅圖根本無法正常提取。
所以,本程序存在一定的局限性,只能處理一些背景不太復雜、二值化之后不會出現過多長曲線的紙幣圖。
(2)
淺色背景無法正常識別。
本程序的邊緣檢測方法是圖像二值化后利用背景和紙幣之間的黑白差異來尋找紙幣的邊緣。當人民幣的背景為淺色時,二值化的時候會將淺色自動二值化為白色(1),而紙幣內部只有少部分會二值化為黑色,但邊緣周圍仍為白色,這樣一來根本無法區分紙幣和背景,所以用imfill填充后無法清除地看到二值圖的邊緣。
以下是實驗圖片:
從圖中可以看到,二值化后整幅圖片除了中央一少部分其他地方均被二值化為白色,所以輪廓提取失敗了。
2.關于邊緣檢測的兩種算法的問題。
小組成員首先使用了edge函數中使用sobel算子的檢測方法。但是通過實驗發現,當處理一些背景比較“干凈”的圖片時,方法可行;當背景中有一些干擾時,邊緣檢測和提取會出現各種問題。經過上網查詢和思考,我們決定使用另一種邊緣檢測和提取的方法,即二值化+填充空洞+bwperim函數的方法。下圖是edge函數的邊緣檢測圖像。
從這幅圖可以看出,用edge函數得到的邊緣雖然完整,但是內部圖像卻仍然存在,有時會干擾邊緣位置確定的結果,所以本次課程設計我們選擇第二種方法。
下圖是背景中存在干擾的圖像和經edge函數處理得到的剪切圖。
由圖可知,sobel算子邊緣檢測在這種情況下無法正常運行。
七.心得體會
通過這次的課程設計,我們對圖像的識別又有了一個新的思路,同時了解了很多關于matlab的專業知識,熟悉了很多函數的用法,并且對編寫程序的過程中出現的各種問題有了了解,對于以后的學習有著莫大的好處。通過這次課程設計,我們深知自己還有很多不足,相信在接下來的時間里,我們會不斷改正、完善我們的程序。
參考文獻:
《matlab初學者教程(翻譯版)》
《基于matlab的四種人民幣識別的方法》
邵愛剛
《數字信號處理(清華大學出版社)》
附錄:
程序代碼:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%-------------【課程設計課題】100元,50元,20元人民幣的識別---------------%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%—————————————————————————%
%----------------圖像預處理部分------------------%
%—————————————————————————%
%邊緣檢測
%
im=imread('50yuan.jpg');%讀取原圖
%
figure(1)
%
subplot(2,2,1)
%
imshow(im);
%
title('原始圖像');%顯示原圖
%
im=im2bw(im);%轉二值圖像
%
subplot(2,2,2)
%
imshow(im)
%
title('二值圖像');%顯示二值圖像
%
im2=imfill(im,'holes');%填充“空洞”
%
F=bwperim(im2);%輪廓提取(bwperim函數用于二值圖像的輪廓提取)
%
subplot(2,2,3)
%
imshow(im2);
%
title('填充后的圖像')%顯示填充后的%
subplot(2,2,4)
%
imshow(F);
%
title('提取出的輪廓')
%以下是利用edge函數和sobel算子進行的邊緣檢測
I=imread('imfill100.jpg');
I1=rgb2gray(I);
n=1;
H=1/(n*n)*ones(n,n);
I2=imfilter(I1,H);
figure(1)
subplot(1,3,1)
imshow(I)
title('原圖')
subplot(1,3,2)
imshow(I1)
title('灰度圖')
subplot(1,3,3)
imshow(I2)
title('濾波后的圖')
F=edge(I2,'sobel');%sobel算子邊緣檢測
figure(2)
imshow(F)
%邊緣提取主要算法
[m
n]=size(F)%j將圖像數據賦值到矩陣,m為行數,n為列數
F=double(F)%將圖像數據轉換為double類型
k=0;l=0;%變量初始化
%左右邊緣提取
%*******方法簡述:兩邊同時一行一行檢測,****%
%*******把每行輪廓所在的列數記下,然后******%
%*******求眾數.***************************%
for
i=1:m
for
j=1:n
if
F(i,j)~=0%0代表黑色,如果F(i,j)不是黑色(則是圖像區域)
k=k+1;
left(k)=j;
for
j1=n:-1:j
if
F(i,j1)~=0
l=l+1;
right(l)=j1
break
end
end
break
end
end
end
%計算眾數,求出左右邊界
right=mode(right)
left=mode(left)
%上下邊界提取
k=0;l=0;
for
j=1:n
for
i=1:m
if
F(i,j)~=0%0代表黑色,如果F(i,j)不是黑色(則是圖像區域)
k=k+1;
up(k)=i;
for
i1=m:-1:i
if
F(i1,j)~=0
l=l+1;
down(l)=i1
break
end
end
break
end
end
end
%計算眾數,求出上下邊界
up=mode(up)
down=mode(down)
%根據得到的邊緣位置截取圖像
pic=imread('imfill100.jpg')
jianqie=pic(up:down,left:right);
%jianqie=im(up:down,left:right);
figure(2)
subplot(2,1,1)
imshow(im)
title('原圖像')
subplot(2,1,2)
imshow(jianqie)
title('邊緣剪切后的圖像')
%—————————————————————————%
%----------------圖像識別部分--------------------%
%—————————————————————————%
%中央數字提取
[m
n]=size(jianqie)
%F=I(round(0.24*m):round(0.50*m),round(0.25*n):round(0.52*n))
FFv2=jianqie(0.275*m:0.50*m,0.254*n:0.5*n)%截取中央圖像
FFv2=medfilt2(FFv2,[4,4])%4*4矩陣中值濾波
FFv2=FFv2(2:(end-4),2:(end-4));
[mt2
nt2]=size(FFv2)
FFv2_bw=im2bw(FFv2,0.5);%二值化
figure(3)
subplot(4,1,1)
imshow(jianqie)
title('原圖像')
subplot(4,1,2)
imshow(FFv2)
title('中央數字提取+中值濾波后的圖像')
subplot(4,1,3)
imshow(FFv2_bw)
title('二值化后的中央數字圖像')
%紙幣檢測
Ty_100=logical(sum(FFv2_bw)<=(mt2-2));%此處用于檢測中央數字起始和終止的邊緣,當二值圖的某一列存在0(即黑色圖像區域)logical返回TRUE(1)
Ty_100_l=find((Ty_100==1));%把1所在的位置賦值給Ty_100_1
rat_100=(Ty_100_l(end)-Ty_100_l(1))/nt2;%計算圖像區域占剪切區域的比例
if
rat_100>=0.8%如果大于0.8則是100.此處的系數與之前截取中央圖像有關
val_mid=100;%val_mid為檢測結果
else%以下用于檢測50和20
lie_f
=
0;
for
j
=
1:(nt2/2)
for
i
=
1:(mt2/2)
if
~(FFv2_bw(i,j)+lie_f)
lie=j;
lie_f=1;
end
end
end
%
向當前列后
2——6
共5列,取黑白行數
FFv2_bw_f=FFv2_bw(:,(lie+2):(lie+6));
hang(3,:)=mt2;
for
j=1:5
for
i=1:(mt2-2)
if
~(FFv2_bw_f(i,j)+FFv2_bw_f(i+1,j)+FFv2_bw_f(i+2,j))
hang(1,j)=i;%第一行記錄首次黑點行數
for
k=(i+2):(mt2-2)
if
(FFv2_bw_f(k,j)+FFv2_bw_f(k+1,j)+FFv2_bw_f(k+2,j))>=2
hang(2,j)=k+1;%第二行記錄二次白點
for
l=(k+2):mt2
if
~(FFv2_bw_f(l,j))
hang(3,j)=l;%第三行記錄二次黑點
break
end
end
break
end
end
break
end
end
end
[hang_m,hang_n]=size(hang);
hang_new=round(sum(hang,2)/hang_n);
hang_black=hang_new(2)-hang_new(1);%第一個黑點和第二個白點之間的距離
hang_white=hang_new(3)-hang_new(2);%第二個白點和第二個黑點之間的距離
if
hang_black>=hang_white
val_mid
=
50;
else
val_mid
=
20;
end
end
subplot(4,1,4)
imshow('jieguo.jpg')
xlabel([val_mid],'Fontsize',36,'color','r');