📄 zxdib.cpp
字号:
pBitmap[position_l] = 0;
position_l ++;
}
}
//修改当前大区域为已有的区域编号:
else if(!modify)
{
color_area++; //总区域数加一
colorarray[color_area] = 1; //相应的区域标志设为1
position_l=0; //修改大区域像素灰度为它的区域编号
for(m=0; m<dwHeight; m++)
for(n=0; n<dwWidth; n++)
{
if(pBitmap[position_l] == 250)
pBitmap[position_l] = (BYTE) color_area;
position_l ++;
}
}
}
position++;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//种子填充算法:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::SeedGrow(DWORD i,DWORD j,BYTE *pBitmap, DWORD& dwHeight, DWORD& dwWidth, DWORD& Number,BYTE& flag,BYTE& egg,WORD& Delete,BYTE* colorarray)
{
//边界条件
if(i>=dwHeight) return true;
if(i<0) return true;
if(j<0) return true;
if(j>=dwWidth) return true;
DWORD position = i*dwWidth+j;
if(Delete) //??改变量的设置是为了一旦检测出本区域过小时就予以删除时,共享此该代码??may not be so
{
if(colorarray[pBitmap[position]]) //如果该点为已经扫描过的点,则加上标志,用于两个区域的合并:
colorarray[pBitmap[position]] = 2;
}
if(pBitmap[position] != flag) //如果不是目标
return true;
if(Number>6000) return true; //设置递归最大层数
pBitmap[position] = egg; //修改为中间色
Number++; //该区域像素个数加一
//下面使用了四邻域种子填充算法:
SeedGrow(i+1, j, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
// SeedGrow(i+1, j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
SeedGrow(i , j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
// SeedGrow(i-1, j+1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
SeedGrow(i-1, j , pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
// SeedGrow(i-1, j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
SeedGrow(i , j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
// SeedGrow(i+1, j-1, pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 用小矩形去腐蚀输入图像
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Uncover2ValueImageByRect(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth,DWORD dwRectHeight,DWORD dwRectWidth)
{
DWORD i,j,k,l;
DWORD temp;
BYTE* pResult=NULL;
DWORD upgate = (DWORD)(dwRectHeight*dwRectWidth*0.80);
DWORD downgate = (DWORD)(dwRectHeight*dwRectWidth*0.30);
pResult = (BYTE*) new BYTE[dwHeight*dwWidth];
for(j=0; j<dwHeight-dwRectHeight; j++)
for(i=0; i<dwWidth-dwRectWidth; i++)
{
temp = 0;
for(k=0; k<dwRectHeight; k++)
for(l=0; l<dwRectWidth; l++)
{
if(!pBitmap[(j+k)*dwWidth+l+i])
temp ++;
}
if(temp>upgate) //大于给定上门限时
for(k=0; k<dwRectHeight; k++)
for(l=0; l<dwRectWidth; l++)
pResult[(j+k)*dwWidth+l+i]=0;
else if(temp<downgate) //小于给定下门限时
for(k=0; k<dwRectHeight; k++)
for(l=0; l<dwRectWidth; l++)
pResult[(j+k)*dwWidth+l+i]=255;
else //二值化的需要
for(k=0; k<dwRectHeight; k++)
for(l=0; l<dwRectWidth; l++)
pResult[(j+k)*dwWidth+l+i]= pResult[(j+k)*dwWidth+l+i]?255:0;
}
for(i=0;i<dwHeight; i++)
for(j=0;j<dwWidth; j++)
pBitmap[i*dwWidth+j] = pResult[i*dwWidth+j];
delete pResult;
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 通过彩色进行目标的粗定位
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CoarsePositionByColorSegment(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, RECT &rect)
{
// TODO: Add your command handler code here
BYTE * pResult=NULL;
BYTE* pTemp=NULL;
DWORD position,i,j;
DWORD dwRectWidth,dwRectHeight;
if(!ColorBasedSegment(pBitmap,dwHeight,dwWidth,pResult))
{ delete pResult; return false;}
if(!GetRidOfSmallBlock(pResult,dwHeight,dwWidth,255,600))
{ delete pResult; return false;}
if(!ProjectAndFindTargetRegion(pResult,dwHeight,dwWidth,rect))
{ delete pResult; return false;}
if(rect.right - rect.left == dwWidth-1 || rect.bottom - rect.top == dwHeight-1)
{ delete pResult; return false;}
dwRectWidth = rect.right-rect.left;
dwRectHeight = rect.bottom-rect.top;
pTemp =(BYTE*) new BYTE[dwRectWidth*dwRectHeight];
position=0;
for(i=rect.top;i<rect.bottom;i++)
for(j=rect.left;j<rect.right;j++)
{
pTemp[position] = pResult[i*dwWidth+j];
position++;
}
RECT rect1;
if(dwRectHeight>80)
{
ProjectAndFindTargetRegion(pTemp,80,dwRectWidth,rect1);
rect.left = rect1.left + rect.left;
rect.right = rect.left + rect1.right-rect1.left;
// rect.bottom = rect1.bottom + rect.top;
}
delete pTemp;
delete pResult;
if(rect.right-rect.left <20 || rect.bottom - rect.top< 20)
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// pBitmap为灰度图象,flag为目标的灰度值
// 主要思想为:设置了一个迭代深度,将超过深度个像素点的的区域标志为一个小的数字,然后在以后的搜索终若遇
// 到某个区域和该区域相邻,则将两个区域合并之。考虑像“手”一样的情况,有可能和多个已知的区域合并。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::SelectBiggestBlock(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth,BYTE flag,DWORD dwMinBlockSize)
{
DWORD temp = 0;
BYTE colorarray[1000]; //用于合并的标志数组,从第1个(非第0个)开始有效
WORD color_area = 0; //标志已经有个多少个大区域
DWORD i,j,k,temp_color,m,n;
DWORD Number;
WORD Delete;
BYTE egg; //中间颜色值
bool modify; //修改标志
for(i=0;i<260; i++)
colorarray[i] = 0;
DWORD position=0;
DWORD position_l;
for( i=0;i<dwHeight; i++)
for(j=0; j<dwWidth; j++)
{
if(pBitmap[position]==flag) //对每一个点都要检查是否是目标点
{
Number=0; //设置个数为0
egg = 250; //设置中间颜色为250
Delete = color_area+1; //
//使用种子填充法找到改点的所属的整个区域:标志为egg
SeedGrow(i,j,pBitmap,dwHeight,dwWidth,Number,flag,egg,Delete,colorarray);
modify = false;
k=1;
temp_color=0;
//首先将刚刚找到的新区域修改为最开始找到的那个大区域编号
for(k=1; (k<=color_area) && (!modify); k++) //一旦有改变就算完成任务:
{
if( colorarray[k]==2 )
{
modify = true;
temp_color = k;
colorarray[k]=1;
position_l=0;
//扫描整个图像将标志为egg的改为k
for(m=0; m<dwHeight; m++)
for(n=0; n<dwWidth; n++)
{
if(pBitmap[position_l] == egg)
pBitmap[position_l] = (BYTE) k;
position_l++;
}
}
}
//寻找看看是否还和其它的大区域相邻:
while((k<=color_area) && (colorarray[k]!=2))
k++;
//处理多区域杂交的情况
if (k<=color_area)
{
position_l=0;
//扫描整个图像进行如下处理:
for(m=0; m<dwHeight; m++)
for(n=0; n<dwWidth; n++)
{
k = temp_color;
while ((k<=color_area)&&(pBitmap[position_l]))
{
if(colorarray[k] == 2)
{
if(pBitmap[position_l] == k)
pBitmap[position_l] = (BYTE) temp_color;
}
k++;
}
position_l++;
}
k=temp_color; //将已经合并了的区域改掉,为0
while (k<=color_area)
{
if( colorarray[k] ==2 )
colorarray[k] = 0;
k++;
}
}
//如果不牵涉到合并,那么可以确定该区域是一个封闭的完整区域,
//根据其面积大小是否大于给定的门限来确定是否删除之
if((!modify)&&(Number<dwMinBlockSize))
{ //若该区域大小小于给定的阈值,则将其删掉:
DWORD position_l = 0;
for(DWORD m=0; m<dwHeight; m++)
for(DWORD n=0; n<dwWidth; n++)
{
if(pBitmap[position_l] == 250)
pBitmap[position_l] = 0;
position_l ++;
}
}
//修改当前大区域为已有的区域编号:
else if(!modify)
{
color_area++; //总区域数加一
colorarray[color_area] = 1; //相应的区域标志设为1
position_l=0; //修改大区域像素灰度为它的区域编号
for(m=0; m<dwHeight; m++)
for(n=0; n<dwWidth; n++)
{
if(pBitmap[position_l] == 250)
pBitmap[position_l] = (BYTE) color_area;
position_l ++;
}
}
}
position++;
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在图像中截取一片区域(8位或24位)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CutRegionFromPicture(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult, DWORD x_from, DWORD y_from, DWORD x_to, DWORD y_to, WORD flag)
{
DWORD i,j;
if(x_from<0 || x_to >=dwWidth || y_from<0 || y_to >=dwHeight || x_from>x_to || y_from>y_to)
return false;
if(pResult) delete pResult;
pResult = (BYTE*) new BYTE[(x_to-x_from)*(y_to-y_from)*flag/8];
DWORD position=0;
if(flag==8)
{
for(i=y_from; i<y_to; i++)
for(j=x_from; j<x_to; j++)
{
pResult[position] = pBitmap[i*dwWidth+j];
position++;
}
}
else
if(flag==24)
{
for(i=y_from; i<y_to; i++)
for(j=x_from; j<x_to; j++)
{
pResult[position] = pBitmap[(i*dwWidth+j)*3];
position++;
pResult[position] = pBitmap[(i*dwWidth+j)*3+1];
position++;
pResult[position] = pBitmap[(i*dwWidth+j)*3+2];
position++;
}
}
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在图像中截取一片区域(8位或24位)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CutRegionFromPicture(double *pBitmap, DWORD dwHeight, DWORD dwWidth, double *&pResult, DWORD x_from, DWORD y_from, DWORD x_to, DWORD y_to, WORD flag)
{
DWORD i,j;
if(x_from<0 || x_to >=dwWidth || y_from<0 || y_to >=dwHeight || x_from>x_to || y_from>y_to)
return false;
if(pResult) delete pResult;
pResult = (double*) new double[(x_to-x_from)*(y_to-y_from)*flag/8];
DWORD position=0;
if(flag==8)
{
for(i=y_from; i<y_to; i++)
for(j=x_from; j<x_to; j++)
{
pResult[position] = pBitmap[i*dwWidth+j];
position++;
}
}
else
if(flag==24)
{
for(i=y_from; i<y_to; i++)
for(j=x_from; j<x_to; j++)
{
pResult[position] = pBitmap[(i*dwWidth+j)*3];
position++;
pResult[position] = pBitmap[(i*dwWidth+j)*3+1];
position++;
pResult[position] = pBitmap[(i*dwWidth+j)*3+2];
position++;
}
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 将24位彩色图转换为灰度图:
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Translate24To8Color(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
DWORD i,j;
DWORD temp;
if(pResult) delete pResult;
pResult = new BYTE[dwHeight*dwWidth];
for(i=0;i<dwHeight;i++)
for(j=0;j<dwWidth; j++)
{
temp = pBitmap[(i*dwWidth+j)*3]+pBitmap[(i*dwWidth+j)*3+1]+pBitmap[(i*dwWidth+j)*3+2];
temp /= 3;
pResult[i*dwWidth+j] = (BYTE) temp;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 利用两种方法一起来进行粗定位:
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::CoarsePositionByColorAndVariance(BYTE **pBKImage, DWORD dwHeight, DWORD dwWidth, int nBKnumber,BYTE *pBitmap, WORD flag, RECT &rect)
{
//计算通过均值和方差计算出来的rect
if(!CoarsePositionByMeanAndVariance(pBKImage,dwHeight,dwWidth,nBKnumber,pBitmap,rect,flag))
return false;
//将rect内的内容抠出来:
BYTE * pResult=NULL;
CutRegionFromPicture(pBitmap,dwHeight,dwWidth,pResult,rect.left,rect.top,rect.right,rect.bottom,flag);
//计算在扣出的图像中目标的rect1:
RECT rect1;
if(!CoarsePositionByColorSegment(pResult,rect.bottom-rect.top,rect.right-rect.left,rect1))
return false;
//修改原来的rect得到结果:
rect.left += rect1.left;
rect.right = rect.left + rect1.right - rect1.left;
rect.top += rect1.top;
rect.bottom = rect.top + rect1.bottom - rect1.top;
rect.bottom += (rect.bottom - rect.top)/4;
if(rect.bottom> dwHeight) rect.bottom = dwHeight;
delete pResult;
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// 得到色调空间:
//
/////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::GetHSIFromRGB(BYTE *pColorBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
if(pResult) delete pResult;
pResult = new BYTE[dwHeight*dwWidth*3];
double r,g,b;
double x;
DWORD i,j;
double S,H,I;
DWORD position=0;
for(i=0; i<dwHeight; i++)
for(j=0; j<dwWidth; j++)
{
b = (double)(pColorBitmap[position])/255.0;
g = (double)(pColorBitmap[position+1])/255.0;
r = (double)(pColorBitmap[position+2])/255.0;
I = (r+g+b)/3;
x = r;
if( x>g ) x = g;
if( x>b ) x = b;
if(I<0.000001)
S = 0;
else
S = 1-x/I;
if(S<0.000001)
H = 0;
else
{
x = (r-g+r-b)/(2*sqrt((r-g)*(r-g)+(r-b)*(g-b)));
if(x>=1.0)
H = 0;
else
H = (acos(x)/3.1415926)*180;
}
if(g<b) H=360-H;
H = H*255;
H /= 360;
pResult[position] = (BYTE) H;
pResult[position+1] = S*255;
pResult[position+2] = I*255;
position += 3;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//利用HSI空间中的S分量进行分割
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::VarianceByRGB2thColor(BYTE *pColorBitmap, DWORD dwHeight, DWORD dwWidth,BYTE* pBKImage, BYTE *&pResultImage)
{
DWORD i,j;
int counter;
if(pResultImage) delete pResultImage;
pResultImage = new BYTE [dwHeight*dwWidth];
for(i=0;i<dwHeight; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -