📄 videopro.cpp
字号:
lpDst = (unsigned char *)(lpNewDIBBits + lLineBytes * i + j);
// 目标图像中的当前点先赋成白色
*lpDst =0;
*(lpDst + 1) = 0;
*(lpDst + 2) = 0;
// 如果源图像中3×3结构元素对应位置有黑点
// 则将目标图像中的(0,0)点赋成黑色
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
if (T[m * 3 + n] == 0)
continue;
if (*(lpSrc + (1 - m) * lLineBytes +(n - 1) * 3) > 128)
{
*lpDst = 255;
*(lpDst + 1) = 255;
*(lpDst + 2) = 255;
break;
}
}
}
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
}
void CVideoPro::RoadDetect(LPBYTE lpDIBBits, int lHeight, int lWidth)
{
//循环变量
LONG i;
LONG j;
LONG m;
LONG n;
struct LINE ln[480];
int xStart,xEnd;
// 指向源图像的指针
LPBYTE lpSrc;
// 指向缓存图像的指针
LPBYTE lpDst;
// 指向缓存DIB图像的指针
LPBYTE lpNewDIBBits;
HLOCAL hNewDIBBits;
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return;
}
// 锁定内存
lpNewDIBBits = (LPBYTE)LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为0
lpDst = (LPBYTE)lpNewDIBBits;
memset(lpDst, (BYTE)0, lLineBytes * lHeight);
ln[0].StartX=0;
ln[0].EndX=640;
for (i = 1; i < lHeight-50 ; i++)
{
xStart=0;xEnd=0;
do
{
xStart++;
lpSrc = (unsigned char *)(lpDIBBits + lLineBytes * i + 3*xStart);
if(*lpSrc==0)
continue;
else
break;
}while(xStart<lWidth-1);
// if(xStart<ln[i-1].EndX)
ln[i].StartX=xStart;
//else
// continue;
int temp,temp2;
temp=xStart;
do
{
temp++;
lpSrc = (unsigned char *)(lpDIBBits + lLineBytes * i + 3*temp);
if(*lpSrc==255)
continue;
else
break;
}while(temp<lWidth-1);
xEnd=temp;
// if(xEnd>ln[i-1].StartX)
ln[i].EndX=xEnd;
// else
// continue;
}
for (i = 1; i < lHeight-50 ; i++)
{
int x1,x2;
x1=ln[i].StartX;
x2=ln[i].EndX;
for (j = x1; j < x2; j++)
{
// 指向目标图像倒数第j行,第i个象素的指针
*(unsigned char *)(lpNewDIBBits + lLineBytes * i + 3*j)=255;
*(unsigned char *)(lpNewDIBBits + lLineBytes * i + 3*j+1)=255;
*(unsigned char *)(lpNewDIBBits + lLineBytes * i + 3*j+2)=255;
}
}
// 复制腐蚀后的图像
memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
}
void CVideoPro::GuassLaplacian(LPBYTE lpDIBBits, int lHeight, int lWidth)
{
// 循环变量
LONG i;
LONG j;
LONG k;
LONG l;
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
// 不能用char,也不能用::strcpy()
unsigned char* m_temp;
m_temp=new unsigned char [lLineBytes * lHeight];
// 中间变量
int v, p_g;
// 检测模版
int g[25]={-2,-4,-4,-4,-2,
-4, 0, 8, 0,-4,
-4, 8,24, 8,-4,
-4, 0, 8, 0,-4,
-2,-4,-4,-4,-2};
// 复制图象数据到中间缓存
for (i = 0; i < lLineBytes * lHeight; i++)
m_temp[i] = *(lpDIBBits + i);
// 5X5 模版
for (i = 0; i < lWidth; i++) //被处理像素在i列
{
for (j = 0; j < lHeight; j++) //被处理像素在j行
{
v= p_g = 0;
for (k = i - 2; k < i + 3; k++) //5*5模版
{
for (l = j - 2; l < j + 3; l++)
{
// 防止内存溢出
if (k >= 0 && l >= 0 && k < lWidth && l < lHeight)
{
v += *(lpDIBBits + l * lLineBytes + k * 3) * g[p_g];
p_g++;
}
}
}
if (v < 0)
v = 0;
if(v>255)
v=255;
m_temp[j * lLineBytes + i * 3] = v;
m_temp[j * lLineBytes + i * 3 + 1] = v;
m_temp[j * lLineBytes + i * 3 + 2] =v;
}
}
// 回存处理结果到DIB
for(i = 0; i < lLineBytes * lHeight; i++)
*(lpDIBBits + i) = m_temp[i];
// 释放内存
delete[] m_temp;
}
BOOL CVideoPro::TempSobel(LPBYTE lpDIBBits, int lHeight, int lWidth)
{
// 模板高度
int nTempH;
// 模板宽度
int nTempW;
// 模板系数
float fTempC;
// 模板中心元素X坐标
int nTempXc;
// 模板中心元素Y坐标
int nTempYc;
int nX1=-1, nY1=-1, nX2=-1, nY2=-1;
// 模板元素数组
// float aValue[9]={-1.0,0,1.0,-1.414,0,1.414,-1.0,0,1.0};//正边缘90方向算子
float aValue[9]={0,1,2,-1,0,1,-2,-1,0};//135度方向检测算子
// float aValue[9]={1,2,1,0,0,0,-1,-2,-1};
nTempH=3;
nTempW=3;
fTempC=1.0;
nTempXc=1;
nTempYc=1;
//对边界像素不作处理
if( nX1 < nTempXc ) nX1 = nTempXc;
if( nY1 < nTempYc ) nY1 = nTempYc;
if( nX2 < lWidth - nTempW + nTempXc + 1)
nX2 = lWidth- nTempW + nTempXc + 1;
if( nY2 < lHeight - nTempH + nTempYc + 1)
nY2 = lHeight - nTempH + nTempYc + 1;
TemplateOperation(lpDIBBits,aValue, fTempC,
nTempW, nTempH, nTempXc, nTempYc,
nX1, nY1,
nX2, nY2,
lHeight,lWidth );
return TRUE;
}
void CVideoPro::Threshold(LPBYTE lpDIBBits, int lHeight, int lWidth)
{
int i,j;
int nHistogramBuffer[256];
GetIntensity(lpDIBBits,lHeight,lWidth,nHistogramBuffer);
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
float Sigma[256];
float Mean1, Mean2;
//Sigma[256]数组清零
for( i = 0;i < 256; i++) Sigma[i] = 0.0;
int nLevelLow = 0;
int nLevelHigh = 0;
//查找最小灰度值
i = 0;
while(nLevelLow == 0)
{
if( nHistogramBuffer[i] != 0 )
{
nLevelLow = i;
}
i++;
}
//查找最大灰度值
i = 255;
while(nLevelHigh == 0)
{
if( nHistogramBuffer[i] != 0 )
{
nLevelHigh = i;
}
i--;
}
//th循环,小于阈值th的像素归为第一类,大于th的像素归为第二类
//th=0、1、2、…、nLevel。
for(int th = nLevelLow; th <= nLevelHigh; th++)
{
long lGrayLow = 0;
long lGrayHigh = 0;
long lSumLow = 0;
long lSumHigh = 0;
for(i = nLevelLow; i < th; i++)
{
lSumLow += nHistogramBuffer[i];
lGrayLow += i * nHistogramBuffer[i];
}
for(i = th; i <= nLevelHigh; i++)
{
lSumHigh += nHistogramBuffer[i];
lGrayHigh += i * nHistogramBuffer[i];
}
if( lSumLow > 0 )
{
Mean1 = (float)lGrayLow / lSumLow;
}
else
{
Mean1 = 0.0;
}
if( lSumHigh > 0)
{
Mean2 = (float)lGrayHigh / lSumHigh;
}
else
{
Mean2 = 0.0;
}
//计算两类之间的方差
Sigma[th] = (float)lSumLow * lSumHigh
* (Mean1 - Mean2) * (Mean1 - Mean2);
}
//th循环结束,求方差最大的阈值
float MaxSigma = Sigma[nLevelLow];
int Thresh = 0;
for( i = nLevelLow + 1; i <= nLevelHigh; i++)
{
if(MaxSigma < Sigma[i])
{
MaxSigma = Sigma[i];
Thresh = i;
}
}
// 对各像素进行灰度转换lHeight, int lWidth
for (i = 0; i <lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
unsigned char Y= *((unsigned char *)lpDIBBits + 3*lWidth * i + 3*j);
if(Y < Thresh)
{
// 回写灰度值
*((unsigned char *)lpDIBBits + 3*lWidth* i + 3*j) = 0;
*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+1) = 0;
*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+2) = 0;
}else
{
// 回写灰度值
*((unsigned char *)lpDIBBits + 3*lWidth* i + 3*j) = 255;
*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+1) = 255;
*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+2) = 255;
}
}
}
}
void CVideoPro::GetIntensity(LPBYTE lpDIBBits, int lHeight, int lWidth, int *nNs_Y)
{
// 循环变量
LONG i;
LONG j;
// 变量初始化
memset(nNs_Y, 0, sizeof(nNs_Y));
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
// 对各像素进行灰度转换
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
unsigned char Y = *((unsigned char *)lpDIBBits + lLineBytes * i + 3*j);
// 灰度统计计数
nNs_Y[Y]++;
}
}
}
BOOL CVideoPro::Hough(LPBYTE lpBufBits, LPBYTE lpDIBBits/*原图像*/, int lHeight, int lWidth, WINDOW w)
{
BYTE *lpSrc;
MaxValue MaxValue1;
int iMaxAngleNumber;
int iDist;
int step_distance=1;//步进距离
double step_angle=PI/180;//步进角
//循环变量
int i,k,m;
long s;
int x;
int y;
double sintab[180],costab[180];
BOOL flag;
LUV CoreLuv;
for(x=0;x<180;x++)
{
sintab[x]=sin(x*PI/180);
costab[x]=cos(x*PI/180);
}
//存储变换域中的两个最大值
//计算变换域的尺寸
m = (int) (sqrt(lWidth*lWidth + lHeight*lHeight)/step_distance);
//角度从0-180,每格step_angle 度
iMaxAngleNumber = int(PI/step_angle);
int *buf,**lpTransArea;
HGLOBAL hbuf,hDistAlpha;
//分配内存用来处理数据
if(( hbuf=GlobalAlloc(GHND,2*m*iMaxAngleNumber* sizeof(int)))==NULL){
//MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
buf=(int *)GlobalLock(hbuf);
//分配内存用来处理数据
if(( hDistAlpha=GlobalAlloc(GHND,2*m* sizeof(int)))==NULL){
//MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
lpTransArea=(int **)GlobalLock(hDistAlpha);
for(i=0;i<2*m;i++)
{
lpTransArea[i]=buf+i*180;//置每行的首地址,每行180度
memset(lpTransArea[i],0,180);//计数单元初始化为零
}
// 计算图像每行的字节数
LONG lLineBytes = 3*lWidth ;
int count=0;
GetCoreRegion(lpDIBBits, lHeight, lWidth, &CoreLuv);
for(y =w.BottomY;y<w.TopY;y++)
{
for(x =w.LeftX;x<w.RightX;x++)
{
// 指向源图像第j行,第i个象素的指针
lpSrc = (BYTE *)(lpBufBits + lLineBytes * y + 3*x);
//如果是白点,则在变换域的对应各点上加1
flag=HorizonEdgeJudge(lpDIBBits,CoreLuv,\
lHeight, lWidth, y, x, 3);
if( (*lpSrc==255)&& flag)
{ //注意步长
for(k=w.MinAngle; k<w.MaxAngle;k++)
{ //计算距离:
s =(long)(x*costab[k]+y*sintab[k]);
//变换域的对应点上加1
if(s>=0)
lpTransArea[s][k]++;
else
lpTransArea[int(s+2*m)][k]++;
}
}
}
}
MaxValue1.Value=0;
//找到第一个最大值点
for (iDist=0; iDist<2*m;iDist++)
{
for(k=0; k<iMaxAngleNumber;k++)
{
if(lpTransArea[iDist][k]>MaxValue1.Value)
{
MaxValue1.Value = lpTransArea[iDist][k];
MaxValue1.Dist = iDist;
MaxValue1.AngleNumber = k;
}
}
}
m_HoughPara=MaxValue1;
int tt;
int cc=0;
POINT StartPoint,EndPoint,MidPoint;
/* HGLOBAL hLine;
//分配内存用来处理数据
if(( hLine=GlobalAlloc(GHND,MaxValue1.Value* sizeof(int)))==NULL){
//MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
buf=(int *)GlobalLock(hbuf);
*/
POINT* line=new POINT[MaxValue1.Value];
// POINT line[26];
//如果直线为偏水平的,按列,下面按x检测
if((MaxValue1.AngleNumber>=45) && (MaxValue1.AngleNumber<=135))
{
for(x =w.LeftX;x<w.RightX;x++)
{
for(y =w.BottomY;y<w.TopY;y++)
{
int temp=(int)(x*costab[MaxValue1.AngleNumber]+y*sintab[MaxValue1.AngleNumber] ) ;
if(temp<0)
tt=(2*m+temp);
else
tt=temp;
if( MaxValue1.Dist==tt &&( lpBufBits[lLineBytes * y +3*x]==255) )
{
*(lpDIBBits + lLineBytes * y +3*x)=0;
*(lpDIBBits + lLineBytes * y +3*x+1)=255;
*(lpDIBBits + lLineBytes * y +3*x+2)=0;
line[cc].x=x;
line[cc].y=y;
cc++;
}
}
}
}
else//如果直线为偏竖直的,按行,并且下面按y来检测
{
for(y =w.BottomY;y<w.TopY;y++)
{
for(x =w.LeftX;x<w.RightX;x++)
{
int temp=(int)(x*costab[MaxValue1.AngleNumber]+y*sintab[MaxValue1.AngleNumber] ) ;
if(temp<0)
tt=(2*m+temp);
else
tt=temp;
if( MaxValue1.Dist==tt &&( *(lpBufBits+ lLineBytes * y +3*x)==255) )
{
*(lpDIBBits + lLineBytes * y +3*x)=0;
*(lpDIBBits + lLineBytes * y +3*x+1)=255;
*(lpDIBBits + lLineBytes * y +3*x+2)=0;
line[cc].x=x;
line[cc].y=y;
cc++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -