📄 videopro.cpp
字号:
// VideoPro.cpp : implementation file
//
#include <stdafx.h>
#include "AGV.h"
#include "VideoPro.h"
#include <math.h>
//#include "Hough.h"
#include "HSI.h"
// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
// 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
// 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
// biWidth'
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CVideoPro
CVideoPro::CVideoPro()
{
}
CVideoPro::~CVideoPro()
{
}
/////////////////////////////////////////////////////////////////////////////
// CVideoPro message handlers
BOOL CVideoPro::ToGray(LPBYTE lpBytes,int lHeight,int lWidth)
{
int i,j;
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
// 获取各颜色分量
unsigned char B= *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);
// 计算灰度值
unsigned char Y = (77 * R + 150 * G + 29 * B) / 256;
// unsigned char U = 128+(-44 * R -87* G + 131* B)/256 ;
// unsigned char V = 128+(131 * R - 110 * G -21 * B)/256 ;
// 回写灰度值
*((unsigned char *)lpBytes + 3*lWidth* i + 3*j) =Y ;
*((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1) = Y;
*((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+2) = Y;
}
}
return TRUE;
}
//RGB24使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
//注意在内存中RGB各分量的排列顺序为:BGR BGR BGR…。
BOOL CVideoPro::RgbTrans(LPBYTE lpBytes, int lHeight, int lWidth)
{
int i,j;
int leftX,leftY;
int rightX,rightY;
RGB rgb;
HSI hsi;
LUV luv;
// LONG result;
// 对各像素进行灰度转换
// 计算图像每行的字节数
leftX=int(0.2*lWidth);
leftY=int(0.05*lHeight);
rightX=int(0.8*lWidth);
rightY=int(0.4*lHeight);
double SumI,SumH,SumS;
double Hue,Int,Sat;
SumI=SumH=SumS=0;
// unsigned char YY,UU,VV;
/*
for (i = leftY; i < rightY; i ++)
{
for (j = leftX; j <rightX; j ++)
{
// 获取各颜色分量
unsigned char B= *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);
rgb.b=B;
rgb.g=G;
rgb.r=R;
RgbToHsi(&rgb,&hsi);
// *((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=(unsigned char )(255*(hsi.Intensity));
SumI=SumI+hsi.Intensity;
SumH=SumH+hsi.Hue;
SumS=SumS+hsi.Saturation;
}
}
Int=SumI/(rightY-leftY)/(rightX-leftX);
Hue=SumH/(rightY-leftY)/(rightX-leftX);
Sat=SumS/(rightY-leftY)/(rightX-leftX);
*/
LUV Coreluv;
GetCoreRegion(lpBytes, lHeight, lWidth, &Coreluv);
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
// 获取各颜色分量
unsigned char B = *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);
rgb.r=R;
rgb.g=G;
rgb.b=B;
/*
rgb.r=212;
rgb.g=178;
rgb.b=143;
*/
double l0,u0,v0,rp;
l0=115.68;
u0=4.27;
v0=-2.50;
/* //灰色水泥路面参考值
l0=Coreluv.l;//126.38;
u0=Coreluv.u;//33.51;
v0=Coreluv.v;//29.14;
*/
RgbToLuv(&rgb,&luv);
rp=sqrt((luv.l-l0)*(luv.l-l0)+(luv.u-u0)*(luv.u-u0)+(luv.v-v0)*(luv.v-v0));
// double
//RgbToHsi(&rgb,&hsi);//hsi.Hue>0.85* Hue && hsi.Hue<0.99* Hue &&hsi.Saturation>0.805* Sat &&
// if ( hsi.Hue>30.47 && hsi.Hue<35)
if ( rp<15)
{
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=255;
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+1)=255;
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+2)=255;
}
else
{
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=0;
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+1)=0;
*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+2)=0;
}
}
}
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* MedianFilter()
*
* 参数:
* HDIB hDIB - 待处理的DIB
*
* 返回值:
* 返回值
*
* 说明:
* 该函数将彩色位图进行中值滤波处理
*
************************************************************************/
void CVideoPro::MedianFilter(LPBYTE lpDIBBits, int lHeight, int lWidth)
{
// 循环变量
LONG i;
LONG j;
LONG k;
LONG l;
// 掩码模版
unsigned char mask[9];
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
// 申请并分配中间缓存
HLOCAL hLocal = LocalAlloc(GHND, lWidth * 3* lHeight);
if (hLocal == NULL)
return;
LPBYTE m_temp = (LPBYTE)LocalLock(hLocal);
//复制图像数据
memcpy( m_temp, lpDIBBits, lWidth *3* lHeight );
// 模版滤波
for (i = 0; i < lWidth; i++) //被处理像素在i列
{
for (j = 0; j < lHeight; j++) //被处理像素在j行
{
// 索引
int id = 0;
// 进行小区域模版滤波
for (k = i - 1; k < i + 2; k++)
{
for(l = j - 1; l < j + 2; l++)
{
// 防止内存溢出
if (k >= 0 && l >= 0 && k < lWidth && l < lHeight)
{
mask[id] = *((unsigned char *)lpDIBBits + l * lLineBytes + k * 3);
id++;
}
}
}
// 中间变量
unsigned char T;
// 冒泡排序法
for (k = 0; k < 8; k++)
{
for (l = 8; l > k; l--)
{
if (mask[l] < mask[l - 1])
{
T = mask[l];
mask[l] = mask[l - 1];
mask[l - 1] = T;
}
}
}
//中值排序法start
/* int i;
int nHisto[256];
int nMedian,nSize=9;
for( i = 0; i < 256; i++) nHisto[ i ] = 0;
//统计相同灰度值出现的次数
for( i = 0; i < nSize; i++)
{
nHisto[(int)mask[i]]++;
}
//取直方图的中值
int nCount = 0;
for( i = 0; i < 256; i++)
{
//存放直方图中相同灰度值出现次数的累加和
nCount += nHisto[i];
if(nCount >= (int)(nSize / 2 + 1))
{
nMedian = i;
break;
}
}
//中值排序法end;
*/
m_temp[j * lWidth* 3 + i* 3 ]=mask[4]; //nMedian;
}
}
// 将转换后的中间缓存数据回存到DIB
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j) =
*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j+1) =
*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j+2) = m_temp [ lWidth * i* 3 +j* 3];
}
}
LocalUnlock(hLocal);
LocalFree(hLocal);
}
void CVideoPro::GetIntensity(LPBYTE lpDIBBits, int lHeight, int lWidth, int *nNs_Y,WINDOW w)
{
// 循环变量
LONG i;
LONG j;
// 变量初始化
memset(nNs_Y, 0, sizeof(nNs_Y));
// 计算图像每行的字节数
LONG lLineBytes = lWidth * 3;
// 对各像素进行灰度转换
for (i = w.BottomY; i < w.TopY; i ++)
{
for (j = w.LeftX; j < w.RightX; j ++)
{
unsigned char Y = *((unsigned char *)lpDIBBits + lLineBytes * i + 3*j);
// 灰度统计计数
nNs_Y[Y]++;
}
}
}
void CVideoPro::Threshold(LPBYTE lpDIBBits, int lHeight, int lWidth,WINDOW w)
{
int i,j;
int nHistogramBuffer[256];
GetIntensity(lpDIBBits,lHeight,lWidth,nHistogramBuffer, w);
// 计算图像每行的字节数
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;
}
}
// 对各像素进行灰度转换
for (i = w.BottomY; i < w.TopY; i ++)
{
for (j = w.LeftX; j < w.RightX; 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;
}
}
}
}
BOOL CVideoPro::Hough(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];
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;
for(y =w.BottomY;y<w.TopY;y++)
{
for(x =w.LeftX;x<w.RightX;x++)
{
// 指向源图像第j行,第i个象素的指针
lpSrc = (BYTE *)(lpDIBBits + lLineBytes * y + 3*x);
//如果是白点,则在变换域的对应各点上加1
if( *lpSrc==255)
{ //注意步长
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(fabs(s))+m][k]++;
lpTransArea[int(s+2*m)][k]++;
}
}
}
}
//找到变换域中的最大值点 && fabs(k-90)>5
MaxValue1.Value=0;
//找到最大值点
for (iDist=0; iDist<2*m;iDist++)
{
for(k=w.MinAngle; k<w.MaxAngle;k++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -