Question:以下兩幅映像,判斷出哪個有孔,並計算出圖中勺子的最窄處的寬度?
我用vc++編寫的識別架構如下:
1.運行介面開啟映像:
2.點擊地區分割與提取:
3.進行多次中值濾波,然後進行一次一階微分運算,運算結果放大兩倍,然後去25二值化得到邊界圖:
然後計算最後操那個圖的像素總值,2.bmp顯示結果為接近6000;求得最短就離為31個像素點,利用length=nmin/28.346這個即可求出距離。
關鍵代碼:
/*----Threshold----二值化處理------------------------
image_in 輸入映像資料指標
image_out 輸出映像資料指標
xsize 映像寬度
ysize 映像高度
thresh 閾值(0-255)
mode 處理方法(1,2)
--------------------------------------------------*/
void Threshold(BYTE *image_in,BYTE*image_out,int xsize,int ysize,int thresh,int mode)
{
inti,j;
for(j=0;j<ysize;j++)
{
for(i=0;i<xsize;i++)
{
switch(mode)
{
case2:
if(*(image_in+i+j*xsize)<=thresh)
*(image_out+i+j*xsize)=HIGH;
else
*(image_out+i+j*xsize)=LOW;
break;
default:
if(*(image_in+i+j*xsize)>=thresh)
*(image_out+i+j*xsize)=HIGH;
else
*(image_out+i+j*xsize)=LOW;
break;
}
}
}
}
//中值子函數
int median_value(BYTE c[9])
{
inti,j,buf;
for(j=0;j<8;j++){
for(i=0;i<8;i++){
if(c[i+1]<c[i]){
buf=c[i+1];
c[i+1]=c[i];
c[i]=buf;
}
}
}
returnc[4];
}
//中值濾波
void Median(BYTE *image_in, BYTE*image_out, int xsize, int ysize)
{
inti,j;
unsignedchar c[9];
for(i=1;i<ysize-1;i++){
for(j=1;j<xsize-1;j++){
c[0]=*(image_in+(i-1)*xsize+j-1);
c[1]=*(image_in+(i-1)*xsize+j);
c[2]=*(image_in+(i-1)*xsize+j+1);
c[3]=*(image_in+i*xsize+j-1);
c[4]=*(image_in+i*xsize+j);
c[5]=*(image_in+i*xsize+j+1);
c[6]=*(image_in+(i+1)*xsize+j-1);
c[7]=*(image_in+(i+1)*xsize+j);
c[8]=*(image_in+(i+1)*xsize+j+1);
*(image_out+i*xsize+j)=median_value(c);
}
}
}
/*--------------------------提取輪廓-----------------------------*
//1階微分邊沿檢出(梯度運算元)
amp //輸出像素值倍數
roberts運算元:g(x,y)=abs(f(x,y)-f(x+1,y+1))+abs(f(x,y+1)-f(x+1,y))
Roberts邊緣檢測運算元是一種利用局部差分運算元尋找邊緣的運算元,Robert運算元影像處理後結果邊緣不是很平滑。
經分析,由於Robert運算元通常會在映像邊緣附近的地區內 產生較寬的響應,
故採用上述運算元檢測的邊緣映像常需做細化處理,邊緣定位的精度不是很高。
卷積運算:可看作是加權求和的過程,使用到的映像地區中的每個像素
分別於卷積核(權矩陣)的每個元素對應相乘,所有乘積之和作為地區中心像素的新值。
連續空間的卷積定義是f(x)與g(x)的卷積是 f(t-x)g(x) 在t從負無窮到正無窮的積分值.t-x要在f(x)定義域內
所以看上去很大的積分實際上還是在一定範圍的
把積分符號換成求和就是離散空間的卷積定義了.那麼在映像中卷積卷積地是什麼意思呢,
就是映像就是映像f(x),模板是g(x),然後將模版g(x)在模版中移動,每到一個位置,
就把f(x)與g(x)的定義域相交的元素進行乘積並且求和,得出新的映像一點,就是被卷積後的映像.
------------------------------------------------------------------*/
void Differential(BYTE *image_in, BYTE*image_out, int xsize, int ysize, float amp)
{
staticint cx[9]={0,0,0,0,1,0,0,0,-1}; //運算元X(roberts)
staticint cy[9]={0,0,0,0,0,1,0,-1,0}; //運算元y(roberts)
intd[9];
inti,j,dat;
floatxx,yy,zz;
for(j=1;j<ysize-1;j++)
{
for(i=1;i<xsize;i++)
{
d[0]=*(image_in+(j-1)*xsize+i-1);
d[1]=*(image_in+(j-1)*xsize+i);
d[2]=*(image_in+(j-1)*xsize+i+1);
d[3]=*(image_in+j*xsize+i-1);
d[4]=*(image_in+j*xsize+i);
d[5]=*(image_in+j*xsize+i+1);
d[6]=*(image_in+(j+1)*xsize+i-1);
d[7]=*(image_in+(j+1)*xsize+i);
d[8]=*(image_in+(j+1)*xsize+i+1);//在映像上取出3*3的像素值
xx=(float)(cx[0]*d[0]+cx[1]*d[1]+cx[2]*d[2]+cx[3]*d[3]+cx[4]*d[4]+
cx[5]*d[5]+cx[6]*d[6]+cx[7]*d[7]+cx[8]*d[8]);
yy=(float)(cy[0]*d[0]+cy[1]*d[1]+cy[2]*d[2]+cy[3]*d[3]+cy[4]*d[4]+
cy[5]*d[5]+cy[6]*d[6]+cy[7]*d[7]+cy[8]*d[8]);
zz=(float)(amp*sqrt(xx*xx+yy*yy));
dat=(int)zz;
if(dat>255)dat=255;
*(image_out+j*xsize+i)=dat;
}
}
}
//膨脹
void Dilation(BYTE *image_in, BYTE*image_out, int xsize, int ysize)
{
inti,j;
for(j=1;j<ysize-1;j++){
for(i=1;i<xsize-1;i++){
*(image_out+j*xsize+i)=*(image_in+j*xsize+i);
if(*(image_in+(j-1)*xsize+i-1)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+(j-1)*xsize+i)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+(j-1)*xsize+i+1)==HIGH)
*(image_out+j*xsize+i+1)=HIGH;
if(*(image_in+j*xsize+i-1)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+j*xsize+i+1)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+j*xsize+i)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+(j+1)*xsize+i-1)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+(j+1)*xsize+i+1)==HIGH)
*(image_out+j*xsize+i)=HIGH;
if(*(image_in+(j+1)*xsize+i)==HIGH)
*(image_out+j*xsize+i)=HIGH;
}
}
}
//腐蝕
void Erodible(BYTE *image_in, BYTE*image_out, int xsize, int ysize)
{
inti,j;
for(j=1;j<ysize-1;j++){
for(i=1;i<xsize-1;i++){
*(image_out+j*xsize+i)=*(image_in+j*xsize+i);
if(*(image_in+(j-1)*xsize+i-1)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+(j-1)*xsize+i)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+(j-1)*xsize+i+1)==LOW)
*(image_out+j*xsize+i+1)=LOW;
if(*(image_in+j*xsize+i-1)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+j*xsize+i+1)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+j*xsize+i)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+(j+1)*xsize+i-1)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+(j+1)*xsize+i+1)==LOW)
*(image_out+j*xsize+i)=LOW;
if(*(image_in+(j+1)*xsize+i)==LOW)
*(image_out+j*xsize+i)=LOW;
}
}
}
/********************************************************************/
//求像素總和
int i,j;
for(j=1;j<m_nysize-1;j++){
for(i=1;i<m_nxsize-1;i++){
*(m_pImage_out+j*m_nxsize+i)=*(m_pImage_in+j*m_nxsize+i);
if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)
m_nSum++;
}
}
SetDlgItemInt(IDC_SUM,m_nSum,TRUE);
/**********************************************************************/
求最短距離
int i,j;
intxx,yy;
intjj=0;
intii=0;
intsumiy[429]={0};
intsumjy[429]={0};
intsum[429]={1};
intiy[116]={0};
intjy[116]={0};
intnmin=100;//最短距離初值
for(j=1;j<m_nysize-1;j++)
{
for(i=1;i<m_nxsize-1;i++)//求出某一行在橫座標方向上的左起像素豈起始點
{
//*(m_pImage_out+j*m_nxsize+i)=*(m_pImage_in+j*m_nxsize+i);
if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)
xx=1;
if(xx==1)
{
iy[jj]=i;
jj++;
}
}
sumiy[j]=iy[1];
for(i=m_nxsize-1;i>1;i--)//求出某一行在橫座標方向上的右起像素豈起始點
{
if(*(m_pImage_in+j*m_nxsize+i-1)==HIGH)
yy=1;
if(ii==1)
{
jy[ii]=i;
ii++;
}
}
sumjy[j]=jy[1];
sum[j]=abs(sumjy[j]-sumiy[j]);//求出某一行在橫座標方向上的像素區間
}
for(j=1;j<427;j++)
{
//求出所有行中在在橫座標方向像素區間最小的距離
if((sum[j]>30) && (sum[j]<100))//排除錯誤成分
{
if( sum[j]<nmin )
{
nmin=sum[j];
}
}
}
SetDlgItemInt(IDC_MIN,nmin,TRUE);