📄 barrecogview.cpp
字号:
for(i=0; i<ImageHeight; i++)
{
if(arPixelV[i]>tempMax)
tempMax = arPixelV[i];
arMark[i] = false;
}
for(i=0; i<ImageHeight-1; i++)
{
//计算差分
arDifference[i] = arPixelV[i+1] - arPixelV[i];
//如果该行像素足够多且变化不大,标记为true
if( (abs(arDifference[i])<20) && (arPixelV[i]>(0.75*tempMax)) )
arMark[i] = true;
}
//确定包含条码的行
int iLengthThrehold = 40;
int iCount;
for(i=0; i<ImageHeight-iLengthThrehold; i++)
{
iCount = 0;
for(j=0; j<iLengthThrehold; j++)
{
if(arMark[i+j] == true)
iCount++;
}
if(iCount >= 37)
{
ImageTop = i+10; //确定顶部
break;
}
}
for(i=ImageHeight-1; i>=iLengthThrehold-1; i--)
{
iCount = 0;
for(j=0; j<iLengthThrehold; j++)
{
if(arMark[i-j] == true)
iCount++;
}
if(iCount >= 37) //iLengthThrehold-3
{
ImageBottom = i-10; //确定底部
break;
}
}
//寻找包含条形码的区域,
//线寻找水平方向上黑象素最大的列
//寻找左边缘,为了保证鲁棒性,在已经确定的上下边界内全局搜索
for(i=ImageTop; i<=ImageBottom; i++)
{
for(j=2; j<ImageWidth; j++)
{
if(*(ImageArray+lRowBytes*(i)+(j-1))==(BYTE)255 && *(ImageArray+lRowBytes*(i)+(j))==(BYTE)0)
{
arLeftEdge[i] = j;
break;
}
}
}
//为消除噪声的干扰,下面确定准确的左边界
tempMax = 0;
int iMax = 0;
for(i=ImageTop; i<=ImageBottom; i++)
{
if(arLeftEdge[i] > tempMax)
{
tempMax = arLeftEdge[i];
iMax = i;
}
}
//倾斜度不能大于1/10
iCount = 0;
for(i=ImageTop; i<=ImageBottom; i++)
{
if( abs(tempMax-arLeftEdge[i]) < abs(i-iMax)/6+1 )
{
iCount++;
}
}
if( (iCount/(ImageBottom-ImageTop))<0.6 )
return false;
//调整起点
for(i=iMax; i>ImageTop; i--)
{
if( abs(arLeftEdge[i]-arLeftEdge[i-1])>=2 )
{
if(*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]-1))-*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]))==(BYTE)255)
arLeftEdge[i-1] = arLeftEdge[i];
else if(*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]-2))-*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]-1))==(BYTE)255)
arLeftEdge[i-1] = arLeftEdge[i]-1;
else if(*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]))-*(ImageArray+lRowBytes*(i-1)+(arLeftEdge[i]+1))==(BYTE)255)
arLeftEdge[i-1] = arLeftEdge[i]+1;
else
arLeftEdge[i-1] = arLeftEdge[i];
}
}
for(i=iMax; i<ImageBottom; i++)
{
if(i == ImageBottom)
break;
if( abs(arLeftEdge[i]-arLeftEdge[i+1])>=2 )
{
if(*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]-1))-*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]))==(BYTE)255)
arLeftEdge[i+1] = arLeftEdge[i];
else if(*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]-2))-*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]-1))==(BYTE)255)
arLeftEdge[i+1] = arLeftEdge[i]-1;
else if(*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]))-*(ImageArray+lRowBytes*(i+1)+(arLeftEdge[i]+1))==(BYTE)255)
arLeftEdge[i+1] = arLeftEdge[i]+1;
else
arLeftEdge[i+1] = arLeftEdge[i];
}
}
int n;
//搜索出所有的宽度
for(n=0; n<29; n++)
{
//搜索条的右边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
for(j = arLeftEdge[i]+1; j<ImageWidth; j++)
{
if(*(ImageArray+lRowBytes*(i)+(j-1))==(BYTE)0 && *(ImageArray+lRowBytes*(i)+(j))==(BYTE)255)
{
arLeftEdge1[i] = j;
break;
}
}
arDelta[i] = arLeftEdge1[i] - arLeftEdge[i];
}
//假定条和空的宽度最多为11
//排序,可以认为最中间的5个宽度是平均宽度
for(i=ImageTop; i<ImageBottom; i++)
tempArray[i] = arDelta[i];
for(i=ImageTop; i<ImageBottom; i++)
{
for(j=ImageBottom; j>i; j--)
{
int tempSwap;
if(tempArray[j] < tempArray[j-1])
{
tempSwap = tempArray[j];
tempArray[j] = tempArray[j-1];
tempArray[j-1] = tempSwap;
}
}
}
if(tempArray[ImageTop+(ImageBottom-ImageTop)/2+2]-tempArray[ImageTop+(ImageBottom-ImageTop)/2-2]>1)
return false;
else
arWidth[2*n] = tempArray[ImageTop+(ImageBottom-ImageTop)/2];
//调整下一列边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
if(abs(arDelta[i] - arWidth[2*n])>2)
arLeftEdge1[i] = arLeftEdge[i] + arWidth[2*n];
arLeftEdge[i] = arLeftEdge1[i];
}
//搜索空的右边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
for(j = arLeftEdge[i]+1; j<ImageWidth; j++)
{
if( (*(ImageArray+lRowBytes*(i)+(j-1))==(BYTE)255) && (*(ImageArray+lRowBytes*(i)+(j))==(BYTE)0) )
{
arLeftEdge1[i] = j;
break;
}
}
arDelta[i] = arLeftEdge1[i] - arLeftEdge[i];
}
//假定条和空的宽度最多为11
//排序,可以认为最中间的5个宽度是平均宽度
for(i=ImageTop; i<ImageBottom; i++)
tempArray[i] = arDelta[i];
for(i=ImageTop; i<ImageBottom; i++)
{
for(j=ImageBottom; j>i; j--)
{
int tempSwap;
if(tempArray[j] < tempArray[j-1])
{
tempSwap = tempArray[j];
tempArray[j] = tempArray[j-1];
tempArray[j-1] = tempSwap;
}
}
}
if(tempArray[ImageTop+(ImageBottom-ImageTop)/2+2]-tempArray[ImageTop+(ImageBottom-ImageTop)/2-2]>1)
return false;
else
arWidth[2*n+1] = tempArray[ImageTop+(ImageBottom-ImageTop)/2];
//调整下一列边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
if(abs(arDelta[i] - arWidth[2*n+1])>2)
arLeftEdge1[i] = arLeftEdge[i] + arWidth[2*n+1];
arLeftEdge[i] = arLeftEdge1[i];
}
}
//搜索最后一个条的右边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
for(j = arLeftEdge[i]+1; j<ImageWidth; j++)
{
if( (*(ImageArray+lRowBytes*(i)+(j-1))==(BYTE)0) && (*(ImageArray+lRowBytes*(i)+(j))==(BYTE)255) )
{
arLeftEdge1[i] = j;
break;
}
}
arDelta[i] = arLeftEdge1[i] - arLeftEdge[i];
}
//假定条和空的宽度最多为11
//排序,可以认为最中间的5个宽度是平均宽度
for(i=ImageTop; i<ImageBottom; i++)
tempArray[i] = arDelta[i];
for(i=ImageTop; i<ImageBottom; i++)
{
for(j=ImageBottom; j>i; j--)
{
int tempSwap;
if(tempArray[j] < tempArray[j-1])
{
tempSwap = tempArray[j];
tempArray[j] = tempArray[j-1];
tempArray[j-1] = tempSwap;
}
}
}
if(tempArray[ImageTop+(ImageBottom-ImageTop)/2+2]-tempArray[ImageTop+(ImageBottom-ImageTop)/2-2]>1)
return false;
else
arWidth[2*n] = tempArray[ImageTop+(ImageBottom-ImageTop)/2];
//调整下一列边缘
for(i=ImageTop; i<=ImageBottom; i++)
{
if(abs(arDelta[i] - arWidth[2*n+1])>2)
arLeftEdge1[i] = arLeftEdge[i] + tempArray[ImageTop+(ImageBottom-ImageTop)/2];
arLeftEdge[i] = arLeftEdge1[i];
}
return true;
}
BOOL CBarRecogView::Recognize()
{
//总共有7×12+3×2+5= 95个单位宽度
//有4×12+3×2+5=59个宽度,
int i;
int result[12];
double mx = 0.0; //平均宽度
for(i=0; i<59; i++)
mx += (double)arWidth[i];
mx /= 95.0;
//起始条文
for(i=0; i<3; i++)
{
double dTemp = (double)arWidth[i]/mx;
if( dTemp<0.6 || dTemp>1.4 )
break;
}
//起始码不符合要求
//if(i<3)
// return false;
//识别前6个
for(i=0; i<6; i++)
{
result[i] = JudgNum(arWidth[i*4+3], arWidth[i*4+4], arWidth[i*4+5], arWidth[i*4+6], mx);
}
//识别后6个
for(i=6; i<12; i++)
{
result[i] = JudgNum(arWidth[i*4+8], arWidth[i*4+9], arWidth[i*4+10], arWidth[i*4+11], mx);
}
//判断码制
if( result[0]==7 && result[1]==7 )
{
strcpy(strCodeStyle,"条形码类型:ISSN\n\n编码: 9");
}
else if( result[0]==7 && result[1]==8 )
{
strcpy(strCodeStyle,"条形码类型:ISBN\n\n编码: 9");
}
else
strcpy(strCodeStyle,"条形码类型:Unknown!\n\n编码: 9");
//判断是否全部识别出来
for(i=0; i<12; i++)
if(result[i] == -1)
return false;
// CString strTemp;
// strCodeNumber.Format("");
for(i=0; i<12; i++)
{
// strTemp.Format("%d", result[i]);
// strCodeNumber += strTemp;
strCodeNumber[i]=(char)(result[i]+0x30);
}
strCodeNumber[i]='\0';
int t1=0,t2=0;
for(i=0;i<12;i+=2)
{
t1+=result[i];
}
for(i=1;i<11;i+=2)
{
t2+=result[i];
}
if((10-(t1*3+(t2+9))%10)!=result[11])
{MessageBox("校验出错!", "识别结果", MB_ICONERROR | MB_OK);
SystemCode='x';
}
strcat(strCodeStyle,strCodeNumber);
strcat(strCodeStyle," ");
return true;
}
int CBarRecogView::JudgNum(int w1, int w2, int w3, int w4, double mx)
{
double a1, a2, a3;
int ia1, ia2, ia3;
a1 = (double)(w1+w2)/mx;
a2 = (double)(w2+w3)/mx;
a3 = (double)(w3+w4)/mx;
ia1 = (int)(a1+0.5);
ia2 = (int)(a2+0.5);
ia3 = (int)(a3+0.5);
//判断该码值
if( (ia1==5 && ia2==3 && ia3==2) || (ia1==2 && ia2==3 && ia3==5) )
return 0;
if( (ia1==4 && ia2==4 && ia3==3) || (ia1==3 && ia2==4 && ia3==4) )
{
if(ia1 == 4)
{
double dw2 = (double)w2/mx;
if(dw2 < 2.4)
return 1;
else if(dw2 > 2.6)
return 7;
else return -1;
}
if(ia1 == 3)
{
double dw3 = (double)w3/mx;
if(dw3 < 2.4)
return 1;
else if(dw3 > 2.6)
return 7;
else return -1;
}
}
if( (ia1==3 && ia2==3 && ia3==4) || (ia1==4 && ia2==3 && ia3==3) )
{
if(ia1 == 3)
{
double dw4 = (double)w4/mx;
if(dw4 < 2.4)
return 2;
else if(dw4 > 2.6)
return 8;
else return -1;
}
if(ia1 == 4)
{
double dw1 = (double)w1/mx;
if(dw1 < 2.4)
return 2;
else if(dw1 > 2.6)
return 8;
else return -1;
}
}
if( (ia1==5 && ia2==5 && ia3==2) || (ia1==2 && ia2==5 && ia3==5) )
return 3;
if( (ia1==2 && ia2==4 && ia3==5) || (ia1==5 && ia2==4 && ia3==2) )
return 4;
if( (ia1==3 && ia2==5 && ia3==4) || (ia1==4 && ia2==5 && ia3==3) )
return 5;
if( (ia1==2 && ia2==2 && ia3==5) || (ia1==5 && ia2==2 && ia3==2) )
return 6;
if( (ia1==4 && ia2==2 && ia3==3) || (ia1==3 && ia2==2 && ia3==4) )
return 9;
return false;
}
void CBarRecogView::OnRecog()
{
// TODO: Add your command handler code here
CBarRecogDoc* pDoc = GetDocument();
BeginWaitCursor(); //更改光标形状;
if(PreProcess()!=FALSE) //调用处理函数;
{if(Recognize()==false)
{MessageBox("无法识别!", "识别结果", MB_ICONERROR | MB_OK);
return;
}
if(SystemCode=='x'){SystemCode=' ';return;}
MessageBox(strCodeStyle, "识别结果", MB_ICONINFORMATION | MB_OK);
}
else
{if(Step<3)
MessageBox("无法识别!\n\n请执行灰度转换,二值化和滤波操作!", "识别结果", MB_ICONERROR | MB_OK);
else
MessageBox("无法识别!", "识别结果", MB_ICONERROR | MB_OK);
}
pDoc->SetModifiedFlag(TRUE); //设置脏标记;
pDoc->UpdateAllViews(NULL); //更新视图;
EndWaitCursor(); //恢复光标
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -