教你使用Matlab制作圖形驗證碼生成器(app designer)
突然發現cla函數也可以應用到app designer控件上,因而對部分內容做出更改,將繪制隱藏像素刷新的方式改為用cla
原
hold(acAxes,'off'); image(acAxes,[-1,0],[-1,0],ones(1,1,3),'visible','off'); hold(acAxes,'on'); delete(findobj('tag','ax'));
新
cla(acAxes) cla(ax)
0效果
1字符圖片生成
如果我們單純的用text繪制圖形,就無法做到效果中符號和符號邊緣兩個顏色,也無法做到更大程度的變形,因此我們需要將字符轉換為矩陣形式。
想要實現也非常簡單,我們隻需要創建一個不可視的fig,在其上繪制字符,保存fig為png格式圖片,再通過imread讀取圖片,就能獲得字符矩陣:
第一次運行程序因為要生成字符圖片因而會比較慢,再次運行就可以讀取之前已經生成過的圖片啦:
% 字符圖片矩陣構造 ======================================================== % 以下為字符圖片創建過程 % 原理為構造隱藏的figure和axes % 在其上用text繪制字符並保存figure為圖片 % 導入圖片 if ~exist('Materials','dir') mkdir('Materials'); end fig=figure('units','pixels',... 'position',[20 80 200 200],... 'Numbertitle','off',... 'Color',[1 1 1],... 'resize','off',... 'visible','off',... 'menubar','none'); ax=axes('Units','pixels',... 'parent',fig,... 'Color',[1 1 1],... 'Position',[0 0 200 200],... 'XLim',[0 200],... 'YLim',[0 200],... 'XColor',[1 1 1],... 'YColor',[1 1 1]); strPic{length(strElement)}=[]; for i=1:length(strElement) % 若是不存在該字符圖片則生成,否則直接導入 if ~exist(['.\Materials\',strElement(i),'.png'],'file') delete(findobj('tag','textStr')); text(ax,100,100,strElement(i),'HorizontalAlignment',... 'center','FontSize',140,'tag','textStr','FontWeigh','bold') saveas(fig,['.\Materials\',strElement(i),'.png']); % 保存圖片 end tempPic=imread(['.\Materials\',strElement(i),'.png']); % 讀取圖片 strPic{i}=imresize(tempPic,[150,150]); % 重新調整圖片大小 end
2刷新按鈕生成
大傢可以看到這個按鈕的樣式與大部分按鈕不同:
實際上這是一個HTML控件,輸入html文件的位置就可以形成類似嵌入頁面的效果:
acHTML=uihtml(acFigure); acHTML.HTMLSource='.\Materials\textbtn.html'; acHTML.DataChangedFcn=@refresh; acHTML.Position=[300 50 88 26];
如代碼所示,我們導入的是Materials文件夾內的textbtn.html文件
textbtn.html長這樣:
<!DOCTYPE html> <html> <head> <meta charset=UTF-8> <script type="text/javascript"> function setup(htmlComponent) { document.getElementById("btnonclink").addEventListener("click", function(event) { htmlComponent.Data="test"; }); } </script> </head> <body> <a href="" id=" rel="external nofollow" rel="external nofollow" rel="external nofollow" btnonclink">看不清?</a> </body> </html>
當然為瞭防止大傢不會創建,我在m文件中寫瞭一段能夠自動創建html文件的代碼,原理就是將字符串信息寫入txt,再將txt文件後綴改為html:
% .html文件自動生成及引入 - - - - - - - - - - - - - - - - - - - - - - - - - htmlContent={'<!DOCTYPE html><html><head><meta charset=UTF-8>'; '<script type="text/javascript">'; 'function setup(htmlComponent){'; 'document.getElementById("btnonclink").addEventListener("click",function(event){'; 'htmlComponent.Data="test";});}</script></head>'; '<body><a href="" id=" rel="external nofollow" rel="external nofollow" rel="external nofollow" btnonclink">看不清?</a></body></html>'}; if ~exist('.\Materials\textbtn.html','file') fid=fopen('.\Materials\textbtn.txt','w'); for i=1:length(htmlContent) fprintf(fid,'%s\r\n',htmlContent{i}); end fclose(fid); copyfile('.\Materials\textbtn.txt','.\Materials\textbtn.html'); delete('.\Materials\textbtn.txt') end
3圖片處理
3.1圖像任意方向拉伸
這部分原理就是將圖像旋轉一定角度後,在豎直方向進行拉伸後再旋轉回去
3.2字符邊緣
這部分原理將字符均值濾波後,把不完全是黑色的部分設置為灰色,後期再設置為其他顏色
3.3圖像處理部分代碼
randColor=@()randi([0,200],[1,3]); % 生成隨機顏色的匿名函數 % 從圖像集合中提取圖像 tPic=strPic{randiNums(ii)}; tPic=tPic(:,:,1); % 將圖像旋轉-拉伸-旋轉 randiTheta1=randi([0,90]); randiTheta2=randi([-30,30]); randiLenth=randi([0,70]); tPic=imrotate(255-tPic,randiTheta1,'bilinear','crop'); tPic=imresize(tPic,[150+randiLenth,150]); tPic=imrotate(tPic,-randiTheta1+randiTheta2,'bilinear','crop'); % 將圖像邊緣進行模糊,並將模糊的部分數值設置為150 tPic=255-imfilter(tPic,I_5); tPic(tPic~=0&tPic~=255)=150; % 為符號和符號邊緣賦予不同顏色 tempColor1=randColor();tempColor2=randColor(); tempPicR=tPic;tempPicG=tPic;tempPicB=tPic; tempPicR(tPic==150)=tempColor1(1);tempPicR(tPic==0)=tempColor2(1); tempPicG(tPic==150)=tempColor1(2);tempPicG(tPic==0)=tempColor2(2); tempPicB(tPic==150)=tempColor1(3);tempPicB(tPic==0)=tempColor2(3); tempPic_3=uint8(zeros([size(tPic),3])); tempPic_3(:,:,1)=tempPicR; tempPic_3(:,:,2)=tempPicG; tempPic_3(:,:,3)=tempPicB;
4線條和散點生成
散點就是生成一堆隨機位置點和一些隨機顏色後用scatter函數繪制,線條是生成散點後使用’spline’插值方法插值成線後再繪制:
randColor=@()randi([0,200],[1,3]); % 生成隨機顏色的匿名函數 randColor_n=@(n)randi([0,200],[n,3])./255; % 生成n個隨機顏色的匿名函數 randPoint_n=@(n)[randi([5,195],[n,1]),randi([5,65],[n,1])];% 生成n個隨機點的匿名函數 % 繪制散點 pPonintsNum=randi([6,10]); pPoints=randPoint_n(pPonintsNum); pPointsColor=randColor_n(pPonintsNum); scatter(acAxes,pPoints(:,1),pPoints(:,2),6,'filled',... 'CData',pPointsColor,'AlphaData',0.6) % 繪制線 lPonintsNum=randi([5,7]); lPoints=randPoint_n(lPonintsNum); lPointsColor=[randColor()./255,0.6]; x_lPoints=interp1(1:lPonintsNum,lPoints(:,1),1:0.01:lPonintsNum,'spline'); y_lPoints=interp1(1:lPonintsNum,lPoints(:,2),1:0.01:lPonintsNum,'spline'); plot(acAxes,x_lPoints,y_lPoints,'Color',lPointsColor,'LineWidth',1.5)
5關於圖像存儲
由於目前版本uifigure還不支持存儲為圖像,因此我們繪制圖像是在figure和uifigure分別繪制一遍,其中figure依舊是不可見狀態,主要用於將圖片驗證碼保存為png格式,可以在完整代碼中看出這一點。
同時,本程序的設置為,每次刷新圖形驗證碼,都會刷新當前文件夾下authCode.png為最新的驗證碼,如需要保存請及時將其改名或復制另存:
6關於驗證碼對比
首先就是需要提取框內驗證碼:
codeInPut=acEditField.Value;
因為我們的驗證碼字符都是大寫的,將輸入的文本用upper函數變為大寫:
codeInPut=upper(codeInPut);
同時我們因為0和O長的太像,所以不對其進行區分,直接將輸入的驗證碼中的0改為O:
codeInPut(codeInPut=='0')='O';
之後就能夠用strcmp函數將當前驗證碼和輸入的驗證碼進行對比:
if strcmp(codeInPut,authCode) msgbox('驗證碼正確') else msgbox('驗證碼錯誤') end
7完整代碼
function authCode strElement=char([49:57,65:90]); % 1-9,A-Z的字符 randColor=@()randi([0,200],[1,3]); % 生成隨機顏色的匿名函數 randColor_n=@(n)randi([0,200],[n,3])./255; % 生成n個隨機顏色的匿名函數 randPoint_n=@(n)[randi([5,195],[n,1]),randi([5,65],[n,1])];% 生成n個隨機點的匿名函數 global authCode; % 全局變量:驗證碼 % 字符圖片矩陣構造 ======================================================== % 以下為字符圖片創建過程 % 原理為構造隱藏的figure和axes % 在其上用text繪制字符並保存figure為圖片 % 導入圖片 if ~exist('Materials','dir') mkdir('Materials'); end fig=figure('units','pixels',... 'position',[20 80 200 200],... 'Numbertitle','off',... 'Color',[1 1 1],... 'resize','off',... 'visible','off',... 'menubar','none'); ax=axes('Units','pixels',... 'parent',fig,... 'Color',[1 1 1],... 'Position',[0 0 200 200],... 'XLim',[0 200],... 'YLim',[0 200],... 'XColor',[1 1 1],... 'YColor',[1 1 1]); strPic{length(strElement)}=[]; for i=1:length(strElement) % 若是不存在該字符圖片則生成,否則直接導入 if ~exist(['.\Materials\',strElement(i),'.png'],'file') delete(findobj('tag','textStr')); text(ax,100,100,strElement(i),'HorizontalAlignment',... 'center','FontSize',140,'tag','textStr','FontWeigh','bold') saveas(fig,['.\Materials\',strElement(i),'.png']); % 保存圖片 end tempPic=imread(['.\Materials\',strElement(i),'.png']); % 讀取圖片 strPic{i}=imresize(tempPic,[150,150]); % 重新調整圖片大小 end % 更改fig ax樣式,為方便後期驗證碼存儲 fig.Position=[100 100 200 70]; ax.Position=[1 1 199.5 70]; ax.XTick=[]; ax.YTick=[]; ax.XLim=[0,200]; ax.YLim=[0,70]; ax.XColor=[0.7 0.7 0.7]; ax.YColor=[0.7 0.7 0.7]; ax.Box='on'; ax.YDir='reverse'; hold(ax,'on'); % APP designer窗口構建 ==================================================== acFigure=uifigure(); acFigure.Position=[100 100 370 90]; acFigure.Name='authCode'; acFigure.Resize='off'; acAxes=uiaxes(acFigure); acAxes.Position=[10 10 200 70]; acAxes.XTick=[]; acAxes.YTick=[]; acAxes.XLim=[0,200]; acAxes.YLim=[0,70]; acAxes.XColor=[0.7 0.7 0.7]; acAxes.YColor=[0.7 0.7 0.7]; acAxes.Box='on'; acAxes.YDir='reverse'; hold(acAxes,'on'); acEditField=uieditfield(acFigure,'text'); acEditField.Position=[220 52 70 23]; acEditField.FontSize=16; acEditField.FontWeight='bold'; acEditField.FontColor=[0.3,0.3,0.3]; % .html文件自動生成及引入 - - - - - - - - - - - - - - - - - - - - - - - - - htmlContent={'<!DOCTYPE html><html><head><meta charset=UTF-8>'; '<script type="text/javascript">'; 'function setup(htmlComponent){'; 'document.getElementById("btnonclink").addEventListener("click",function(event){'; 'htmlComponent.Data="test";});}</script></head>'; '<body><a href="" id=" rel="external nofollow" rel="external nofollow" rel="external nofollow" btnonclink">看不清?</a></body></html>'}; if ~exist('.\Materials\textbtn.html','file') fid=fopen('.\Materials\textbtn.txt','w'); for i=1:length(htmlContent) fprintf(fid,'%s\r\n',htmlContent{i}); end fclose(fid); copyfile('.\Materials\textbtn.txt','.\Materials\textbtn.html'); delete('.\Materials\textbtn.txt') end acHTML=uihtml(acFigure); acHTML.HTMLSource='.\Materials\textbtn.html'; acHTML.DataChangedFcn=@refresh; acHTML.Position=[300 50 88 26]; % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - acButton=uibutton(acFigure); acButton.Position=[220 15 140 30]; acButton.Text='確 認 驗 證 碼'; acButton.BackgroundColor=[0.31 0.58 0.80]; acButton.FontColor=[1 1 1]; acButton.FontWeight='bold'; acButton.FontSize=14; acButton.ButtonPushedFcn=@verify; % 回調函數 ================================================================ function refresh(~,~) cla(acAxes) cla(ax) I_5=fspecial('average',[5,5]); % 5*5均值濾波模板 randiNums=randi([1,length(strElement)],[1,4]); authCode=strElement(randiNums); % 驗證碼 disp(authCode) for ii=1:4 tPic=strPic{randiNums(ii)}; tPic=tPic(:,:,1); %tempPic(tempPic<250)=150; % 將圖像旋轉-拉伸-旋轉 randiTheta1=randi([0,90]); randiTheta2=randi([-30,30]); randiLenth=randi([0,70]); tPic=imrotate(255-tPic,randiTheta1,'bilinear','crop'); tPic=imresize(tPic,[150+randiLenth,150]); tPic=imrotate(tPic,-randiTheta1+randiTheta2,'bilinear','crop'); % 將圖像邊緣進行模糊,並將模糊的部分數值設置為150 tPic=255-imfilter(tPic,I_5); tPic(tPic~=0&tPic~=255)=150; % 為符號和符號邊緣賦予不同顏色 tempColor1=randColor();tempColor2=randColor(); tempPicR=tPic;tempPicG=tPic;tempPicB=tPic; tempPicR(tPic==150)=tempColor1(1);tempPicR(tPic==0)=tempColor2(1); tempPicG(tPic==150)=tempColor1(2);tempPicG(tPic==0)=tempColor2(2); tempPicB(tPic==150)=tempColor1(3);tempPicB(tPic==0)=tempColor2(3); tempPic_3=uint8(zeros([size(tPic),3])); tempPic_3(:,:,1)=tempPicR; tempPic_3(:,:,2)=tempPicG; tempPic_3(:,:,3)=tempPicB; % 顯示圖片 image(acAxes,[-size(tempPic_3,2)/2,size(tempPic_3,2)/2]./3.5+40*ii+randi([-5,5]),... [-size(tempPic_3,1)/2,size(tempPic_3,1)/2]./3.5+35+randi([-5,5]),... tempPic_3,'AlphaData',tempPic_3(:,:,1)~=255,'Interpolation','bilinear') image(ax,[-size(tempPic_3,2)/2,size(tempPic_3,2)/2]./3.5+40*ii+randi([-5,5]),... [-size(tempPic_3,1)/2,size(tempPic_3,1)/2]./3.5+35+randi([-5,5]),... tempPic_3,'AlphaData',tempPic_3(:,:,1)~=255,'Interpolation','bilinear') end % 繪制散點 pPonintsNum=randi([6,10]); pPoints=randPoint_n(pPonintsNum); pPointsColor=randColor_n(pPonintsNum); scatter(acAxes,pPoints(:,1),pPoints(:,2),6,'filled',... 'CData',pPointsColor,'AlphaData',0.6) scatter(ax,pPoints(:,1),pPoints(:,2),6,'filled',... 'CData',pPointsColor,'AlphaData',0.6) % 繪制線 lPonintsNum=randi([5,7]); lPoints=randPoint_n(lPonintsNum); lPointsColor=[randColor()./255,0.6]; x_lPoints=interp1(1:lPonintsNum,lPoints(:,1),1:0.01:lPonintsNum,'spline'); y_lPoints=interp1(1:lPonintsNum,lPoints(:,2),1:0.01:lPonintsNum,'spline'); plot(acAxes,x_lPoints,y_lPoints,'Color',lPointsColor,'LineWidth',1.5) plot(ax,x_lPoints,y_lPoints,'Color',lPointsColor,'LineWidth',1.5) saveas(fig,'.\authCode.png'); end refresh() function verify(~,~) codeInPut=acEditField.Value; codeInPut=upper(codeInPut); codeInPut(codeInPut=='0')='O'; if strcmp(codeInPut,authCode) msgbox('驗證碼正確') else msgbox('驗證碼錯誤') end end end
註:程序第一次運行由於有html文件及png文件需要生成,因而會比較慢,之後的運行速度會快很多。
對於以前版本沒有uihtml控件可以先嘗試如下代碼:
這裡用正常按鈕替換瞭uihtml控件
function authCode2 strElement=char([49:57,65:90]); % 1-9,A-Z的字符 randColor=@()randi([0,200],[1,3]); % 生成隨機顏色的匿名函數 randColor_n=@(n)randi([0,200],[n,3])./255; % 生成n個隨機顏色的匿名函數 randPoint_n=@(n)[randi([5,195],[n,1]),randi([5,65],[n,1])];% 生成n個隨機點的匿名函數 global authCode; % 全局變量:驗證碼 % 字符圖片矩陣構造 ======================================================== % 以下為字符圖片創建過程 % 原理為構造隱藏的figure和axes % 在其上用text繪制字符並保存figure為圖片 % 導入圖片 if ~exist('Materials','dir') mkdir('Materials'); end fig=figure('units','pixels',... 'position',[20 80 200 200],... 'Numbertitle','off',... 'Color',[1 1 1],... 'resize','off',... 'visible','off',... 'menubar','none'); ax=axes('Units','pixels',... 'parent',fig,... 'Color',[1 1 1],... 'Position',[0 0 200 200],... 'XLim',[0 200],... 'YLim',[0 200],... 'XColor',[1 1 1],... 'YColor',[1 1 1]); strPic{length(strElement)}=[]; for i=1:length(strElement) % 若是不存在該字符圖片則生成,否則直接導入 if ~exist(['.\Materials\',strElement(i),'.png'],'file') delete(findobj('tag','textStr')); text(ax,100,100,strElement(i),'HorizontalAlignment',... 'center','FontSize',140,'tag','textStr','FontWeigh','bold') saveas(fig,['.\Materials\',strElement(i),'.png']); % 保存圖片 end tempPic=imread(['.\Materials\',strElement(i),'.png']); % 讀取圖片 strPic{i}=imresize(tempPic,[150,150]); % 重新調整圖片大小 end % 更改fig ax樣式,為方便後期驗證碼存儲 fig.Position=[100 100 200 70]; ax.Position=[1 1 199.5 70]; ax.XTick=[]; ax.YTick=[]; ax.XLim=[0,200]; ax.YLim=[0,70]; ax.XColor=[0.7 0.7 0.7]; ax.YColor=[0.7 0.7 0.7]; ax.Box='on'; ax.YDir='reverse'; hold(ax,'on'); % APP designer窗口構建 ==================================================== acFigure=uifigure(); acFigure.Position=[100 100 370 90]; acFigure.Name='authCode'; acFigure.Resize='off'; acAxes=uiaxes(acFigure); acAxes.Position=[10 10 200 70]; acAxes.XTick=[]; acAxes.YTick=[]; acAxes.XLim=[0,200]; acAxes.YLim=[0,70]; acAxes.XColor=[0.7 0.7 0.7]; acAxes.YColor=[0.7 0.7 0.7]; acAxes.Box='on'; acAxes.YDir='reverse'; hold(acAxes,'on'); acEditField=uieditfield(acFigure,'text'); acEditField.Position=[220 52 70 23]; acEditField.FontSize=16; acEditField.FontWeight='bold'; acEditField.FontColor=[0.3,0.3,0.3]; acfreshBtn=uibutton(acFigure); acfreshBtn.Text='看不清?'; acfreshBtn.ButtonPushedFcn=@refresh; acfreshBtn.Position=[300 50 60 27]; % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - acButton=uibutton(acFigure); acButton.Position=[220 15 140 30]; acButton.Text='確 認 驗 證 碼'; acButton.BackgroundColor=[0.31 0.58 0.80]; acButton.FontColor=[1 1 1]; acButton.FontWeight='bold'; acButton.FontSize=14; acButton.ButtonPushedFcn=@verify; % 回調函數 ================================================================ function refresh(~,~) cla(acAxes) cla(ax) % hold(acAxes,'off'); % image(acAxes,[-1,0],[-1,0],ones(1,1,3),'visible','off'); % hold(acAxes,'on'); % delete(findobj('tag','ax')); I_5=fspecial('average',[5,5]); % 5*5均值濾波模板 randiNums=randi([1,length(strElement)],[1,4]); authCode=strElement(randiNums); % 驗證碼 disp(authCode) for ii=1:4 tPic=strPic{randiNums(ii)}; tPic=tPic(:,:,1); %tempPic(tempPic<250)=150; % 將圖像旋轉-拉伸-旋轉 randiTheta1=randi([0,90]); randiTheta2=randi([-30,30]); randiLenth=randi([0,70]); tPic=imrotate(255-tPic,randiTheta1,'bilinear','crop'); tPic=imresize(tPic,[150+randiLenth,150]); tPic=imrotate(tPic,-randiTheta1+randiTheta2,'bilinear','crop'); % 將圖像邊緣進行模糊,並將模糊的部分數值設置為150 tPic=255-imfilter(tPic,I_5); tPic(tPic~=0&tPic~=255)=150; % 為符號和符號邊緣賦予不同顏色 tempColor1=randColor();tempColor2=randColor(); tempPicR=tPic;tempPicG=tPic;tempPicB=tPic; tempPicR(tPic==150)=tempColor1(1);tempPicR(tPic==0)=tempColor2(1); tempPicG(tPic==150)=tempColor1(2);tempPicG(tPic==0)=tempColor2(2); tempPicB(tPic==150)=tempColor1(3);tempPicB(tPic==0)=tempColor2(3); tempPic_3=uint8(zeros([size(tPic),3])); tempPic_3(:,:,1)=tempPicR; tempPic_3(:,:,2)=tempPicG; tempPic_3(:,:,3)=tempPicB; % 顯示圖片 image(acAxes,[-size(tempPic_3,2)/2,size(tempPic_3,2)/2]./3.5+40*ii+randi([-5,5]),... [-size(tempPic_3,1)/2,size(tempPic_3,1)/2]./3.5+35+randi([-5,5]),... tempPic_3,'AlphaData',tempPic_3(:,:,1)~=255,'Interpolation','bilinear') image(ax,[-size(tempPic_3,2)/2,size(tempPic_3,2)/2]./3.5+40*ii+randi([-5,5]),... [-size(tempPic_3,1)/2,size(tempPic_3,1)/2]./3.5+35+randi([-5,5]),... tempPic_3,'AlphaData',tempPic_3(:,:,1)~=255,'Interpolation','bilinear') end % 繪制散點 pPonintsNum=randi([6,10]); pPoints=randPoint_n(pPonintsNum); pPointsColor=randColor_n(pPonintsNum); scatter(acAxes,pPoints(:,1),pPoints(:,2),6,'filled',... 'CData',pPointsColor,'AlphaData',0.6) scatter(ax,pPoints(:,1),pPoints(:,2),6,'filled',... 'CData',pPointsColor,'AlphaData',0.6) % 繪制線 lPonintsNum=randi([5,7]); lPoints=randPoint_n(lPonintsNum); lPointsColor=[randColor()./255,0.6]; x_lPoints=interp1(1:lPonintsNum,lPoints(:,1),1:0.01:lPonintsNum,'spline'); y_lPoints=interp1(1:lPonintsNum,lPoints(:,2),1:0.01:lPonintsNum,'spline'); plot(acAxes,x_lPoints,y_lPoints,'Color',lPointsColor,'LineWidth',1.5) plot(ax,x_lPoints,y_lPoints,'Color',lPointsColor,'LineWidth',1.5) saveas(fig,'.\authCode.png'); end refresh() function verify(~,~) codeInPut=acEditField.Value; codeInPut=upper(codeInPut); codeInPut(codeInPut=='0')='O'; if strcmp(codeInPut,authCode) msgbox('驗證碼正確') else msgbox('驗證碼錯誤') end end end
以上就是教你使用Matlab制作圖形驗證碼生成器(app designer)的詳細內容,更多關於Matlab圖形驗證碼生成器的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- 利用Matlab復刻舉牌加油小人生成器
- JavaScript實現頁面動態驗證碼的實現示例
- Python實現自動化發送郵件
- 利用Matlab制作環形相冊效果詳解
- React Native 中實現確認碼組件示例詳解