把ImageDib的unsigned char* m_pImgData转换为IplImage的char* imageData

博主试图将Visual C++的经典人脸识别代码移植到VS2010,遇到了如何将ImageDib的unsigned char* m_pImgData转换为IplImage的char* imageData的问题。在代码移植过程中,数据处理部分成为关键,尤其是涉及图像数据类型的转换。

	今天终于把困扰我三天的问题解决了。

我原本想把Visual C++数字图像模式识别典型案例详解中的人脸定位的CalSim()函数移植到VS2010中的。

但是就被unsigned char* 转换为char* 这个思想给困住了。

贴上书上的原函数:

void FaceDetect::CalSim()
{
	//若灰度图像,则返回
	if(m_nBitCount==8) return;

	//释放旧的输出图像数据及颜色表缓冲区
	if(m_pImgDataOut!=NULL){
		delete []m_pImgDataOut;
		m_pImgDataOut=NULL;
	}
	if(m_lpColorTableOut!=NULL){
		delete []m_lpColorTableOut;
		m_lpColorTableOut=NULL;
	}

	//灰值化后,每像素位数为8比特
	m_nBitCountOut=8;

	//颜色表长度
	m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut);

	//申请颜色表缓冲区,生成灰度图像的颜色表
	if(m_nColorTableLengthOut!=0){
    	m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut];
		for(int i=0; i<m_nColorTableLengthOut;i++){
			m_lpColorTableOut[i].rgbBlue=i;
			m_lpColorTableOut[i].rgbGreen=i;
			m_lpColorTableOut[i].rgbRed=i;
			m_lpColorTableOut[i].rgbReserved=0;
		}
	}

	//输入图像每像素字节数,彩色图像为3字节/像素
	int pixelByteIn=3;
	
	//输入图像每行像素所占字节数,必须是4的倍数
	int lineByteIn=(m_imgWidth*pixelByteIn+3)/4*4;

	//输出图像的宽高,与输入图像相等
	m_imgWidthOut=m_imgWidth;
	m_imgHeightOut=m_imgHeight;

	//输出图像每行像素所占字节数,必须是4的倍数
	int lineByteOut=(m_imgWidth*m_nBitCountOut/8+3)/4*4;

	//申请输出图像位图数据缓冲区
	m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeight];

	//循环变量,图像的坐标
	int i,j,k;
	char c_t1[4];

	for(i=0;i<m_imgHeight;i++){
		for(j=0;j<m_imgWidth;j++){
			*(m_pImgDataOut+i*lineByteOut+j)=255;
		}
	}

	m_pSimArray = new double*[m_imgHeight];
	for(i=0;i<m_imgHeight;i++)
		m_pSimArray[i] = new double[m_imgWidth];

	for(i=0;i<m_imgHeight;i++)
	{
		for (j=0;j<m_imgWidth;j++)
		{
			for(k=0;k<3;k++)
			{
				c_t1[k]=*(m_pImgDataIn1+i*lineByteIn+j*pixelByteIn+k);
			}
			int C_b=(int)c_t1[0]&255;
			int C_g=(int)c_t1[1]&255;
			int C_r=(int)c_t1[2]&255;
			double Cb=(128-37.797*C_r/255-74.203*C_g/255+112*C_b/255);
			double Cr=(128+112*C_r/255-93.786*C_g/255-18.214*C_b/255);
			double tt =(Cb-Cb_Mean)*((Cb-Cb_Mean)*Cov11-(Cr-Cr_Mean)*Cov10)+(Cr-Cr_Mean)*(-(Cb-Cb_Mean)*Cov01+(Cr-Cr_Mean)*Cov00);
			tt =(-0.5*tt)/(Cov00*Cov11-Cov01*Cov10);
			m_pSimArray[i][j]=exp(tt);
		}
	}
	CalMedFl(m_pSimArray,m_imgWidth, m_imgHeight,9);
	double max=0.0;

	for(i=0;i<m_imgHeight;i++)
		for (j=0;j<m_imgWidth;j++)
		{
			if(m_pSimArray[i][j]>max)
				max=m_pSimArray[i][j];
		}
	for( i=0;i<m_imgHeight;i++)
		for (j=0;j<m_imgWidth;j++)
		{
			m_pSimArray[i][j]= m_pSimArray[i][j]/max;
		}

	for(i=0;i<m_imgHeight;i++)
		for(j=0;j<m_imgWidth;j++)
		{
			*(m_pImgDataOut+i*lineByteOut+j)=(int)(m_pSimArray[i][j]*255);
		}
}
void FaceDetect::CalMedFl(double **s, int w, int h, int n)
{

int i,j;
double **temp;
temp = new double*[h+2*(int)(n/2)];
for(i=0;i<h+2*(int)(n/2);i++)
temp[i] = new double[w+2*(int)(n/2)];
for(i=0;i<w+2*(int)(n/2);i++)
for(j=0;j<h+2*(int)(n/2);j++)
temp[j][i] = 0.0;

for(i=0;i<h;i++)
for(j=0;j<w;j++)
temp[i+(int)(n/2)][j+(int)(n/2)]=s[i][j];
for(i=0;i<h;i++)
for(j=0;j<w;j++)
{
s[i][j]=0.0;
for(int r=0;r<n;r++)
for(int c=0;c<n;c++)
s[i][j]+=temp[i+r][j+c];
s[i][j]/=n*n;
}
if(temp!=NULL)
{
for(i=0;i<h+2;i++)
if(temp[i]!=NULL)
delete temp[i];
delete temp;
}

}

前面很多什么调色板啊之类的是不用的。

但对数据的处理就需要经过思考了。


我主要面临的数据处理部分的问题代码是这么一段:

for(i=0;i<m_imgHeight;i++)
	{
		for (j=0;j<m_imgWidth;j++)
		{
			for(k=0;k<3;k++)
			{
				c_t1[k]=*(m_pImgDataIn1+i*lineByteIn+j*pixelByteIn+k);
			}
			int C_b=(int)c_t1[0]&255;
			int C_g=(int)c_t1[1]&255;
			int C_r=(int)c_t1[2]&255;
			double Cb=(128-37.797*C_r/255-74.203*C_g/255+112*C_b/255);
			double Cr=(128+112*C_r/255-93.786*C_g/255-18.214*C_b/255);
			double tt =(Cb-Cb_Mean)*((Cb-Cb_Mean)*Cov11-(Cr-Cr_Mean)*Cov10)+(Cr-Cr_Mean)*(-(Cb-Cb_Mean)*Cov01+(Cr-Cr_Mean)*Cov00);
			tt =(-0.5*tt)/(Cov00*Cov11-Cov01*Cov10);
			m_pSimArray[i][j]=exp(tt);
m_pImgDataIn1的定义是unsigned char*型的,说明其指向的数据范围是0~255.
而我需要转换到IplImage的ImgData是char*型的,着还不是什么问题。
不知道怎么说了。我改过之后的源码贴下去吧。其中C_b,C_g,C_r我把他们改成了unsigned char型了。
	for(i=0;i<img->height;i++)
	{
		for(j=0;j<img->width;j++)
		{
			for(k=0;k<3;k++)
			{
//				if(img->imageData+(img->height-1-i)*img->widthStep+j*3+k>=0)
				c_t1[k]=((img->imageData + i*img->widthStep))[j*3+k];
//					c_t1[k]=*(img->imageData+(img->height-1-i)*img->widthStep+j*3+k);
//				else
//					c_t1[k]=*((img->imageData+(img->height-1-i)*img->widthStep+j*3+k))+256;
			}
			C_b=c_t1[0];
			C_g=c_t1[1];
			C_r=c_t1[2];
			Cb=(128-37.797*C_r/255-74.203*C_g/255+112*C_b/255);
			Cr=(128+112*C_r/255-93.786*C_g/255-18.214*C_b/255);
			double tt =(Cb-Cb_Mean)*((Cb-Cb_Mean)*Cov11-(Cr-Cr_Mean)*Cov10)+(Cr-Cr_Mean)*(-(Cb-Cb_Mean)*Cov01+(Cr-Cr_Mean)*Cov00);
			tt =(-0.5*tt)/(Cov00*Cov11-Cov01*Cov10);
			m_pSimArray[i][j]=exp(tt);
		}
	}


#include <cstdio> #include <cstring> #include <iostream> #include "Windows.h" #include "HCNetSDK.h" #include "PlayM4.h" #include <opencv2\opencv.hpp> #include "cv.h" #include "highgui.h" #include <time.h> #define USECOLOR 1 using namespace std; using namespace std; //-------------------------------------------- int iPicNum=0;//Set channel NO. LONG nPort=-1; HWND hWnd=NULL; void yv12toYUV(char *outYuv, char *inYv12, int width, int height,int widthStep) { int col,row; unsigned int Y,U,V; int tmp; int idx; //printf("widthStep=%d.\n",widthStep); for (row=0; row<height; row++) { idx=row * widthStep; int rowptr=row*width; for (col=0; col<width; col++) { //int colhalf=col>>1; tmp = (row/2)*(width/2)+(col/2); // if((row==1)&&( col>=1400 &&col<=1600)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("row*width+col=%d,width*height+width*height/4+tmp=%d,width*height+tmp=%d.\n",row*width+col,width*height+width*height/4+tmp,width*height+tmp); // } Y=(unsigned int) inYv12[row*width+col]; U=(unsigned int) inYv12[width*height+width*height/4+tmp]; V=(unsigned int) inYv12[width*height+tmp]; // if ((col==200)) // { // printf("col=%d,row=%d,width=%d,tmp=%d.\n",col,row,width,tmp); // printf("width*height+width*height/4+tmp=%d.\n",width*height+width*height/4+tmp); // return ; // } if((idx+col*3+2)> (1200 * widthStep)) { //printf("row * widthStep=%d,idx+col*3+2=%d.\n",1200 * widthStep,idx+col*3+2); } outYuv[idx+col*3] = Y; outYuv[idx+col*3+1] = U; outYuv[idx+col*3+2] = V; } } //printf("col=%d,row=%d.\n",col,row); } //解码回调 视频为YUV数据(YV12),音频为PCM数据 void CALLBACK DecCBFun(long nPort,char * pBuf,long nSize,FRAME_INFO * pFrameInfo, long nReserved1,long nReserved2) { long lFrameType = pFrameInfo->nType; if(lFrameType ==T_YV12) { #if USECOLOR //int start = clock(); IplImage* pImgYCrCb = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3);//得到图像的Y分量 yv12toYUV(pImgYCrCb->imageData, pBuf, pFrameInfo->nWidth,pFrameInfo->nHeight,pImgYCrCb->widthStep);//得到全部RGB图像 IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 3); cvCvtColor(pImgYCrCb,pImg,CV_YCrCb2RGB); //int end = clock(); #else IplImage* pImg = cvCreateImage(cvSize(pFrameInfo->nWidth,pFrameInfo->nHeight), 8, 1); memcpy(pImg->imageData,pBuf,pFrameInfo->nWidth*pFrameInfo->nHeight); #endif //printf("%d\n",end-start); cvShowImage("IPCamera",pImg); cvWaitKey(1); #if USECOLOR cvReleaseImage(&pImgYCrCb); cvReleaseImage(&pImg); #else cvReleaseImage(&pImg); #endif //此时是YV12格式的视频数据,保存在pBuf中,可以fwrite(pBuf,nSize,1,Videofile); //fwrite(pBuf,nSize,1,fp); } /*************** else if (lFrameType ==T_AUDIO16) { //此时是音频数据,数据保存在pBuf中,可以fwrite(pBuf,nSize,1,Audiofile); } else { } *******************/ } ///实时流回调 void CALLBACK fRealDataCallBack(LONG lRealHandle,DWORD dwDataType,BYTE *pBuffer,DWORD dwBufSize,void *pUser) { DWORD dRet; switch (dwDataType) { case NET_DVR_SYSHEAD: //系统头 if (!PlayM4_GetPort(&nPort)) //获取播放库未使用的通道号 { break; } if(dwBufSize > 0) { if (!PlayM4_OpenStream(nPort,pBuffer,dwBufSize,1024*1024)) { dRet=PlayM4_GetLastError(nPort); break; } //设置解码回调函数 只解码不显示 if (!PlayM4_SetDecCallBack(nPort,DecCBFun)) { dRet=PlayM4_GetLastError(nPort); break; } //设置解码回调函数 解码且显示 //if (!PlayM4_SetDecCallBackEx(nPort,DecCBFun,NULL,NULL)) //{ // dRet=PlayM4_GetLastError(nPort); // break; //} //打开视频解码 if (!PlayM4_Play(nPort,hWnd)) { dRet=PlayM4_GetLastError(nPort); break; } //打开音频解码, 需要码流是复合流 if (!PlayM4_PlaySound(nPort)) { dRet=PlayM4_GetLastError(nPort); break; } } break; case NET_DVR_STREAMDATA: //码流数据 if (dwBufSize > 0 && nPort != -1) { BOOL inData=PlayM4_InputData(nPort,pBuffer,dwBufSize); while (!inData) { Sleep(10); inData=PlayM4_InputData(nPort,pBuffer,dwBufSize); OutputDebugString(L"PlayM4_InputData failed \n"); } } break; } } void CALLBACK g_ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser) { char tempbuf[256] = {0}; switch(dwType) { case EXCEPTION_RECONNECT: //预览时重连 printf("----------reconnect--------%d\n", time(NULL)); break; default: break; } } void main() { //--------------------------------------- // 初始化 NET_DVR_Init(); //设置连接时间与重连时间 NET_DVR_SetConnectTime(2000, 1); NET_DVR_SetReconnect(10000, true); //--------------------------------------- // 获取控制台窗口句柄 //HMODULE hKernel32 = GetModuleHandle((LPCWSTR)"kernel32"); //GetConsoleWindow = (PROCGETCONSOLEWINDOW)GetProcAddress(hKernel32,"GetConsoleWindow"); //--------------------------------------- // 注册设备 LONG lUserID; NET_DVR_DEVICEINFO_V30 struDeviceInfo; lUserID = NET_DVR_Login_V30("10.102.7.88", 8000, "admin", "12345", &struDeviceInfo); if (lUserID < 0) { printf("Login error, %d\n", NET_DVR_GetLastError()); NET_DVR_Cleanup(); return; } //--------------------------------------- //设置异常消息回调函数 NET_DVR_SetExceptionCallBack_V30(0, NULL,g_ExceptionCallBack, NULL); //cvNamedWindow("IPCamera"); //--------------------------------------- //启动预览并设置回调数据流 NET_DVR_CLIENTINFO ClientInfo; ClientInfo.lChannel = 1; //Channel number 设备通道号 ClientInfo.hPlayWnd = NULL; //窗口为空,设备SDK不解码只取流 ClientInfo.lLinkMode = 0; //Main Stream ClientInfo.sMultiCastIP = NULL; LONG lRealPlayHandle; lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID,&ClientInfo,fRealDataCallBack,NULL,TRUE); if (lRealPlayHandle<0) { printf("NET_DVR_RealPlay_V30 failed! Error number: %d\n",NET_DVR_GetLastError()); return; } //cvWaitKey(0); Sleep(-1); //fclose(fp); //--------------------------------------- //关闭预览 if(!NET_DVR_StopRealPlay(lRealPlayHandle)) { printf("NET_DVR_StopRealPlay error! Error number: %d\n",NET_DVR_GetLastError()); return; } //注销用户 NET_DVR_Logout(lUserID); NET_DVR_Cleanup(); return; } 转为python语言
最新发布
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值