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