拼接备忘(随笔记)
for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { srcx=(double)(newWidth/2-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2-middleInFinaly+y)/dbZoom ;
逐渐放大的中心。(615,730)。
if( !(srcx>=xl && srcx<=xr && srcy>=yu && srcy<=yd))
外圈设为:但是这样外圈的放大中心在图中间。需要将两个放大中心合在一起,而内圈和外圈图中心位置有偏差。
关键在于把偏差修正!
srcx=(double)(1.5*newWidth-middleInFinalx+x-25*dbZoom)/(3*dbZoom);//补偏差
srcy=(double)(1.5*newHeight-middleInFinaly+y+218*dbZoom)/(3*dbZoom);//此处映射公式为外圈比内圈放大倍数=3。原来是2。
未完待续。
// Imagejoint.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "Imagejoint.h" #include <afxwin.h> #ifdef _DEBUG #define new DEBUG_NEW #endif #include <atlimage.h>//CImage类 #include <locale.h> #include "math.h" using namespace std; //双三次插值系数 double fs(double w) { double a=-0.5; double fs; if (abs(w)<=1) fs=(a+2)*pow(abs(w),3)-(a+3)*pow(abs(w),2)+1; else if (abs(w)>1&&abs(w)<=2) fs=a*pow(abs(w),3)-5*a*pow(abs(w),2)+8*a*abs(w)-4*a; else fs=0; return fs; } HRESULT Imagejoint(PBYTE pbSrc1,PBYTE pbSrc2,int iWidth,int iHeight,double dbZoom,PBYTE pbFinal,PBYTE pbMiddle1,PBYTE pbMiddle2); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;//表示整数类型的函数返回码。n表示整数类型,Ret是Return的缩写,表示返回值,Code表示代码。 setlocale(LC_ALL,"chs"); HMODULE hModule = ::GetModuleHandle(NULL); if (hModule != NULL) { HRESULT hResult1,hResult2; //初始化一些变量 int iWidth,iHeight,iBytePerPixel,iPitch; int x,y; PBYTE pbSrc1=NULL,pbSrc2=NULL,pbFinal=NULL;//源图、目标图 PBYTE pbMiddle1=NULL,pbMiddle2=NULL; PBYTE pbImage=NULL;//load图像后存在这 PDWORD pdwImage=NULL;//用于保存图像 int frame_num=1; double dbZoom=1.25; //起始放大倍数,需要注意!过小外图都填不下。 for(dbZoom=0.7;dbZoom<=1.50;dbZoom+=0.15) { CImage cImage_far; CImage cImage_near; CString farsrc= "1.bmp"; CString nearsrc = "1650.bmp"; LPCTSTR filename1 = (LPCTSTR)farsrc; LPCTSTR filename2 = (LPCTSTR)nearsrc; if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs _tprintf(_T("Fatal Error: MFC initialization failed\n")); nRetCode = 1; } //Load 图像到cImage对象中 hResult1=cImage_far.Load(filename1); hResult2=cImage_near.Load(filename2); if(hResult1!=ERROR_SUCCESS||hResult2!=ERROR_SUCCESS) { _tprintf(_T("源图像文件名错误!\n")); nRetCode= -3; } iWidth=cImage_far.GetWidth(); iHeight=cImage_far.GetHeight(); //分配源图内存 pbSrc1 = (PBYTE)malloc(iWidth*iHeight); pbSrc2 = (PBYTE)malloc(iWidth*iHeight); //分配目标图内存 pbFinal = (PBYTE)malloc(1280*1024); pbMiddle1=(PBYTE)malloc(1280*1024); pbMiddle2=(PBYTE)malloc(1280*1024); if(pbSrc1==NULL||pbSrc2==NULL || pbFinal==NULL ) { _tprintf(_T("内存申请错误!\n")); nRetCode= -4; } //cImage数据存到pbImage,后再转换为源灰度图pbSrc iPitch=cImage_far.GetPitch(); iBytePerPixel=(cImage_far.GetBPP()+7)/8; if(iBytePerPixel==3) { for(y=0;y<iHeight;y++) { //load的图像数据放到pbImage pbImage=(PBYTE)(PBYTE(cImage_far.GetBits())+iPitch*y);//得到的是图像初始像素地址 for(x=0;x<iWidth;x++) { //pbImage转换为灰度图pbSrc pbSrc1[y*iWidth+x]=(pbImage[3*x]*0.15+pbImage[3*x+1]*0.55+pbImage[3*x+2]*0.3); } } } cImage_far.Destroy(); iPitch=cImage_near.GetPitch(); iBytePerPixel=(cImage_near.GetBPP()+7)/8; if(iBytePerPixel==3) { for(y=0;y<iHeight;y++) { //load的图像数据放到pbImage pbImage=(PBYTE)(PBYTE(cImage_near.GetBits())+iPitch*y);//得到的是图像初始像素地址 for(x=0;x<iWidth;x++) { //pbImage转换为灰度图pbSrc pbSrc2[y*iWidth+x]=(pbImage[3*x]*0.15+pbImage[3*x+1]*0.55+pbImage[3*x+2]*0.3); } } } cImage_near.Destroy(); //执行操作 hResult1=Imagejoint(pbSrc1,pbSrc2,iWidth,iHeight,dbZoom,pbFinal,pbMiddle1,pbMiddle2); if(hResult1!=ERROR_SUCCESS) { _tprintf(_T("图像处理错误!\n")); nRetCode= -5; } //处理后保存图像 iWidth=1280; iHeight=1024; cImage_far.Create(iWidth,-iHeight,32); iPitch=cImage_far.GetPitch(); for(y=0;y<iHeight;y++) { pdwImage=(PDWORD)(PBYTE(cImage_far.GetBits())+iPitch*y); for(x=0;x<iWidth;x++) { pdwImage[x]=pbFinal[y*iWidth+x]*0x10101; } } //可预存待保存图像文件名 CString name1="D:/文件及下载相关/桌面/模拟变焦拼接/Matlab_code/result/"; CString name2; //这里要随着帧数改动 name2.Format(_T("%d"),frame_num); CString csTagName; csTagName=name1+name2; csTagName.Trim(); csTagName.MakeUpper(); if(csTagName.Right(4)!=_T(".bmp") ) csTagName.Append(_T(".bmp")); hResult1=cImage_far.Save(csTagName); if(hResult1!=ERROR_SUCCESS) { _tprintf(_T("图像结果保存错误!\n")); nRetCode= -5; } _tprintf(_T("图像处理成功!\n")); nRetCode= ERROR_SUCCESS; if(pbSrc1) free(pbSrc1); if(pbSrc2) free(pbSrc2); if(pbFinal) free(pbFinal); //dbZoom=dbZoom+0.0070; //dbZoom=dbZoom+0.25; frame_num++; }//对应+=0.25倍数的for循环。 } else { _tprintf(_T("Fatal Error: GetModuleHandle failed\n")); nRetCode = 1; } getchar(); return nRetCode; } HRESULT Imagejoint(PBYTE pbSrc1,PBYTE pbSrc2,int iWidth,int iHeight,double dbZoom,PBYTE pbFinal,PBYTE pbMiddle1,PBYTE pbMiddle2) { double phase[33]={0};//16相位,包含端点存在33个距离 for (int i=0;i<33;i++) { double i2=1.0*i; phase[i]=fs(i2/16); } double count_a=0; double count_b=0; double count=0; double w=1; //Matlab中测试获取定值(34:541 -Y,41:728 -X),需要微调。 //int xl=41,xr=720,yu=34,yd=541;//原768*576大小图像中,存在内容的部分。 int xl=1,xr=752,yu=1,yd=574; int transition=25;//渐变像素过渡设置 //旋转中心为图像中心 double rx0=iWidth; double ry0=iHeight; double srcx,srcy,u,v; int xOr,yOr; int newWidth=ceil(dbZoom*iWidth); int newHeight=ceil(dbZoom*iHeight); int middleInFinalx=615;//内圈图像待放置的,处于目标图中的图像中心。(也是图像放大中心) int middleInFinaly=730; for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { srcx=(double)(newWidth/2-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2-middleInFinaly+y)/dbZoom ; xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; int phasex=floor(16*u+0.5);//16相位 int phasey=floor(16*v+0.5); double A1,B1,C1,D1,A2,B2,C2,D2; A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; if( !(srcx>=xl && srcx<=xr && srcy>=yu && srcy<=yd))//越界部分需拼接为外圈大视场图像,远景 { /* srcx=(double)(1.5*newWidth-middleInFinalx+x)/(3*dbZoom);//补偏差 srcy=(double)(1.5*newHeight-middleInFinaly+y)/(3*dbZoom);//此处映射公式为外圈比内圈放大倍数=3。原来是2。 xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle= pbSrc1[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc1[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc1[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc1[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc1[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+2)]*D1*D2; if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; */ srcx=(double)(1.5*newWidth-middleInFinalx+x-35.7*dbZoom)/(3*dbZoom);//补偏差 srcy=(double)(1.5*newHeight-middleInFinaly+y+311.4*dbZoom)/(3*dbZoom);//此处映射公式为外圈比内圈放大倍数=3。原来是2。 xOr = floor(srcx); yOr = floor(srcy); if(xOr>iWidth) xOr=iWidth; if(yOr>iHeight) yOr=iHeight; if(xOr<0) xOr=0; if(yOr<0) yOr=0; pbFinal[y*1280+x]=pbSrc1[(yOr)*iWidth+(xOr)]; //pbFinal[y*1280+x]=255; } /* else if( !(srcx>=xl+transition && srcx<=xr-transition && srcy>=yu+transition && srcy<=yd-transition)) { double weight=1;//代表内圈所占的权重 if(srcx>=xl && srcx<=xl+transition) weight=(srcx-xl)*1.0/transition; else if(srcx>=xr-transition && srcx<=xr) weight=(xr-srcx)*1.0/transition; if(srcy>=yu && srcy<=yu+transition) weight=(srcy-yu)*1.0/transition; else if(srcy>=yd-transition && srcy<=yd) weight=(yd-srcy)*1.0/transition; if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yu && srcy<=yu+transition)) weight=min((srcx-xl),(srcy-yu))*1.0/transition; else if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yd-transition && srcy<=yd)) weight=min((srcx-xl),(yd-srcy))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yu && srcy<=yu+transition)) weight=min((xr-srcx),(srcy-yu))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yd-transition && srcy<=yd)) weight=min((xr-srcx),(yd-srcy))*1.0/transition; //pbFinal[y*1280+x]=255; srcx=(double)(newWidth-middleInFinalx+x)/(2*dbZoom)+6;//补偏差 srcy=(double)(newHeight-middleInFinaly+y)/(2*dbZoom)-3; xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle1= pbSrc1[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc1[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc1[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc1[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc1[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+2)]*D1*D2; //pbMiddle1[y*1280+x]=middle1; if(middle1<=255&&middle1>=0) pbMiddle1[y*1280+x]=middle1; else if(middle1>255) pbMiddle1[y*1280+x]=255; else pbMiddle1[y*1280+x]=0; //外图的渐变区域的值,先存到pbMiddle1中。 //------------------------------------------------------------ srcx=(double)(newWidth/2-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2-middleInFinaly+y)/dbZoom ; xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle2= pbSrc2[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc2[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc2[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc2[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc2[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+2)]*D1*D2; //pbMiddle2[y*1280+x]=middle2; if(middle2<=255&&middle2>=0) pbMiddle2[y*1280+x]=middle2; else if(middle2>255) pbMiddle2[y*1280+x]=255; else pbMiddle2[y*1280+x]=0; //内图的渐变区域的值,再存到pbMiddle2中。 //count++; //count_a+=middle1; //count_b+=middle2; //w=count_a/count-count_b/count; //w=count_a/count_b; //边界融合 double middle3=(1-weight)* pbMiddle1[y*1280+x]+weight*pbMiddle2[y*1280+x]; pbFinal[y*1280+x]=middle3; //if(middle3<=255&&middle3>=0) // pbFinal[y*1280+x]=middle3; // else if(middle3>255) // pbFinal[y*1280+x]=255; // else // pbFinal[y*1280+x]=0; } */ //内圈,核心区域pbSrc2-B else { /* srcx=(double)(newWidth/2-640+x)/dbZoom; srcy=(double)(newHeight/2-512+y)/dbZoom ; double middle3= pbSrc2[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc2[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc2[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc2[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc2[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+2)]*D1*D2; //w=count_a/count-count_b/count; //w=count_a/count_b;//0.762953 //middle3=middle3*w; if(middle3<=255&&middle3>=0) pbFinal[y*1280+x]=middle3; else if(middle3>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; */ pbFinal[y*1280+x]=pbSrc2[(yOr)*iWidth+(xOr)]; } } } /* //亮度平衡部分 double sum1=0,sum2=0; double w2=1; double xl2=0,xr2=0,yu2=0,yd2=0; //xl2=ceil(xl*dbZoom-newWidth/2+640); //xr2=ceil(xr*dbZoom-newWidth/2+640); //yu2=ceil(yu*dbZoom-newHeight/2+512); //yd2=ceil(yd*dbZoom-newHeight/2+512); xl2=ceil((xl+transition)*dbZoom-newWidth/2+640); xr2=ceil((xr-transition)*dbZoom-newWidth/2+640);//右侧细线 yu2=ceil((yu+transition)*dbZoom-newHeight/2+512); yd2=ceil((yd-transition)*dbZoom-newHeight/2+512); for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { if(pbMiddle1[y*1280+x]!=205) sum1+=pbMiddle1[y*1280+x]; if(pbMiddle2[y*1280+x]!=205) sum2+=pbMiddle2[y*1280+x]; } } w2=sum1/sum2;//0.82 ,原来的直接取一个系数。 //统计直方图 double middle1_state[256]={0}; double middle2_state[256]={0}; int gray1=0; int gray2=0; int num1_L=0; int num1_H=0; int num2_L=0; int num2_H=0; int gray1L=0; int gray1H=0; int gray2L=0; int gray2H=0; for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { if(pbMiddle1[y*1280+x]!=205) { gray1=pbMiddle1[y*1280+x]; middle1_state[gray1]++;//按灰度级统计外圈的 } if(pbMiddle2[y*1280+x]!=205) { gray2=pbMiddle2[y*1280+x]; middle2_state[gray2]++;//按灰度级统计内圈的 } } } //统计好后分别找前1/3和后1/3 //先统计总个数 for(int gray=0;gray<256;gray++) { sum1+=middle1_state[gray];//个数之和,共有多少个有效元素。 sum2+=middle1_state[gray]; } //外圈统计中找1/3 for(int gray=0;gray<256;gray++) { num1_L+=middle1_state[gray]; if(num1_L<=sum1/3.0) {gray1L=gray;}//前1/3数量的灰度级是到gray1L。 else ; } for(int gray=255;gray>=0;gray--) { num1_H+=middle1_state[gray]; if(num1_H<=sum1/3.0) {gray1H=gray;}//后1/3数量的灰度级是到gray1H。 else ; } //内圈统计找1/3 for(int gray=0;gray<256;gray++) { num2_L+=middle2_state[gray]; if(num2_L<=sum2/3.0) {gray2L=gray;}//前1/3数量的灰度级是到gray2L。 else ; } for(int gray=255;gray>=0;gray--) { num2_H+=middle2_state[gray]; if(num2_H<=sum2/3.0) {gray2H=gray;}//后1/3数量的灰度级是到gray2H。 else ; } //统计好后,计算A1,A2,B1,B2。双点进行亮度平衡。 double sum1L=0,sum1H=0,sum2L=0,sum2H=0;//用于统计个数 double pix_sum1L=0,pix_sum1H=0,pix_sum2L=0,pix_sum2H=0;//用于累计像素值求和 double A1=0,A2=0,B1=0,B2=0; double w3=1,b3=1;//要用到的,增益和偏置参数 //外圈的1/3计算A1,A2 for(int gray=0;gray<=gray1L;gray++) { sum1L+=middle1_state[gray]; pix_sum1L+=middle1_state[gray]*gray; } for(int gray=255;gray>=gray1H;gray--) { sum1H+=middle1_state[gray]; pix_sum1H+=middle1_state[gray]*gray; } //内圈的1/3计算B1,B2 for(int gray=0;gray<=gray2L;gray++) { sum2L+=middle2_state[gray]; pix_sum2L+=middle2_state[gray]*gray; } for(int gray=255;gray>=gray2H;gray--) { sum2H+=middle2_state[gray]; pix_sum2H+=middle2_state[gray]*gray; } A1=pix_sum1L/sum1L; A2=pix_sum1H/sum1H; B1=pix_sum2L/sum2L; B2=pix_sum2H/sum2H; w3=(A2-A1)/(B2-B1); b3=A1-w3*B1; double middle=0; //=================================================================================== //亮度平衡 for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { if(x>=xl2 && x<=xr2 && y>=yu2 && y<=yd2) { double middle=0; middle=w3*pbFinal[y*1280+x]+b3; //middle=w2*pbFinal[y*1280+x]; if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle ; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; } } } //对渐变范围也做平衡处理: for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { srcx=(double)(newWidth/2-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2-middleInFinaly+y)/dbZoom ; if( !(srcx>=xl && srcx<=xr && srcy>=yu && srcy<=yd)) ; else if( !(srcx>=xl+transition && srcx<=xr-transition && srcy>=yu+transition && srcy<=yd-transition)) { double weight=1;//代表内圈所占的权重 if(srcx>=xl && srcx<=xl+transition) weight=(srcx-xl)*1.0/transition; else if(srcx>=xr-transition && srcx<=xr) weight=(xr-srcx)*1.0/transition; if(srcy>=yu && srcy<=yu+transition) weight=(srcy-yu)*1.0/transition; else if(srcy>=yd-transition && srcy<=yd) weight=(yd-srcy)*1.0/transition; if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yu && srcy<=yu+transition)) weight=min((srcx-xl),(srcy-yu))*1.0/transition; else if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yd-transition && srcy<=yd)) weight=min((srcx-xl),(yd-srcy))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yu && srcy<=yu+transition)) weight=min((xr-srcx),(srcy-yu))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yd-transition && srcy<=yd)) weight=min((xr-srcx),(yd-srcy))*1.0/transition; double middle=0; middle=(1-weight)*pbMiddle1[y*1280+x]+weight*(w3*pbMiddle2[y*1280+x]+b3); //middle=(1-weight)*pbMiddle1[y*1280+x]+weight*(w2*pbMiddle2[y*1280+x]); if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle ; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; } } } */ return ERROR_SUCCESS; }
为什么选择(615,730)。
在当前dbZoom下!很重要!例如当前dbZoom=0.6。
首先,移动内圈至其偏移中心:
其次,对于外圈:中心(640,512)。
srcx=(double)(1.5*newWidth-640+x)/(3*dbZoom);//补偏差
srcy=(double)(1.5*newHeight-512+y)/(3*dbZoom);
使内外圈边界对齐,试验,得出:
int middleInFinalx=620;//内圈图像待放置的,处于目标图中的图像中心。(也是图像放大中心)
int middleInFinaly=705;
srcx=(double)(1.5*newWidth-middleInFinalx+x-20)/(3*dbZoom);//补偏差
srcy=(double)(1.5*newHeight-middleInFinaly+y+193)/(3*dbZoom);
仅在当前dbZoom下有效。。
扩展到任意倍数放大,改为:
srcx=(double)(1.0/2*3*newWidth-middleInFinalx+x-20/0.6*dbZoom)/(3*dbZoom);//补偏差
srcy=(double)(1.0/2*3*newHeight-middleInFinaly+y+193/0.6*dbZoom)/(3*dbZoom);
最后的代码:
// Imagejoint.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "Imagejoint.h" #include <afxwin.h> #ifdef _DEBUG #define new DEBUG_NEW #endif #include <atlimage.h>//CImage类 #include <locale.h> #include "math.h" using namespace std; //双三次插值系数 double fs(double w) { double a=-0.5; double fs; if (abs(w)<=1) fs=(a+2)*pow(abs(w),3)-(a+3)*pow(abs(w),2)+1; else if (abs(w)>1&&abs(w)<=2) fs=a*pow(abs(w),3)-5*a*pow(abs(w),2)+8*a*abs(w)-4*a; else fs=0; return fs; } HRESULT Imagejoint(PBYTE pbSrc1,PBYTE pbSrc2,int iWidth,int iHeight,double dbZoom,PBYTE pbFinal,PBYTE pbMiddle1,PBYTE pbMiddle2); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0;//表示整数类型的函数返回码。n表示整数类型,Ret是Return的缩写,表示返回值,Code表示代码。 setlocale(LC_ALL,"chs"); HMODULE hModule = ::GetModuleHandle(NULL); if (hModule != NULL) { HRESULT hResult1,hResult2; //初始化一些变量 int iWidth,iHeight,iBytePerPixel,iPitch; int x,y; PBYTE pbSrc1=NULL,pbSrc2=NULL,pbFinal=NULL;//源图、目标图 PBYTE pbMiddle1=NULL,pbMiddle2=NULL; PBYTE pbImage=NULL;//load图像后存在这 PDWORD pdwImage=NULL;//用于保存图像 int frame_num=1; double dbZoom=1.25; //起始放大倍数,需要注意!过小外图都填不下。 for(dbZoom=0.66;dbZoom<=1.50;dbZoom+=0.001) { CImage cImage_far; CImage cImage_near; CString farsrc= "1.bmp"; CString nearsrc = "1650.bmp"; LPCTSTR filename1 = (LPCTSTR)farsrc; LPCTSTR filename2 = (LPCTSTR)nearsrc; if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs _tprintf(_T("Fatal Error: MFC initialization failed\n")); nRetCode = 1; } //Load 图像到cImage对象中 hResult1=cImage_far.Load(filename1); hResult2=cImage_near.Load(filename2); if(hResult1!=ERROR_SUCCESS||hResult2!=ERROR_SUCCESS) { _tprintf(_T("源图像文件名错误!\n")); nRetCode= -3; } iWidth=cImage_far.GetWidth(); iHeight=cImage_far.GetHeight(); //分配源图内存 pbSrc1 = (PBYTE)malloc(iWidth*iHeight); pbSrc2 = (PBYTE)malloc(iWidth*iHeight); //分配目标图内存 pbFinal = (PBYTE)malloc(1280*1024); pbMiddle1=(PBYTE)malloc(1280*1024); pbMiddle2=(PBYTE)malloc(1280*1024); if(pbSrc1==NULL||pbSrc2==NULL || pbFinal==NULL ) { _tprintf(_T("内存申请错误!\n")); nRetCode= -4; } //cImage数据存到pbImage,后再转换为源灰度图pbSrc iPitch=cImage_far.GetPitch(); iBytePerPixel=(cImage_far.GetBPP()+7)/8; if(iBytePerPixel==3) { for(y=0;y<iHeight;y++) { //load的图像数据放到pbImage pbImage=(PBYTE)(PBYTE(cImage_far.GetBits())+iPitch*y);//得到的是图像初始像素地址 for(x=0;x<iWidth;x++) { //pbImage转换为灰度图pbSrc pbSrc1[y*iWidth+x]=(pbImage[3*x]*0.15+pbImage[3*x+1]*0.55+pbImage[3*x+2]*0.3); } } } cImage_far.Destroy(); iPitch=cImage_near.GetPitch(); iBytePerPixel=(cImage_near.GetBPP()+7)/8; if(iBytePerPixel==3) { for(y=0;y<iHeight;y++) { //load的图像数据放到pbImage pbImage=(PBYTE)(PBYTE(cImage_near.GetBits())+iPitch*y);//得到的是图像初始像素地址 for(x=0;x<iWidth;x++) { //pbImage转换为灰度图pbSrc pbSrc2[y*iWidth+x]=(pbImage[3*x]*0.15+pbImage[3*x+1]*0.55+pbImage[3*x+2]*0.3); } } } cImage_near.Destroy(); //执行操作 hResult1=Imagejoint(pbSrc1,pbSrc2,iWidth,iHeight,dbZoom,pbFinal,pbMiddle1,pbMiddle2); if(hResult1!=ERROR_SUCCESS) { _tprintf(_T("图像处理错误!\n")); nRetCode= -5; } //处理后保存图像 iWidth=1280; iHeight=1024; cImage_far.Create(iWidth,-iHeight,32); iPitch=cImage_far.GetPitch(); for(y=0;y<iHeight;y++) { pdwImage=(PDWORD)(PBYTE(cImage_far.GetBits())+iPitch*y); for(x=0;x<iWidth;x++) { pdwImage[x]=pbFinal[y*iWidth+x]*0x10101; } } //可预存待保存图像文件名 CString name1="D:/文件及下载相关/桌面/模拟变焦拼接/Matlab_code/result/"; CString name2; //这里要随着帧数改动 name2.Format(_T("%d"),frame_num); CString csTagName; csTagName=name1+name2; csTagName.Trim(); csTagName.MakeUpper(); if(csTagName.Right(4)!=_T(".bmp") ) csTagName.Append(_T(".bmp")); hResult1=cImage_far.Save(csTagName); if(hResult1!=ERROR_SUCCESS) { _tprintf(_T("图像结果保存错误!\n")); nRetCode= -5; } _tprintf(_T("图像处理成功!\n")); nRetCode= ERROR_SUCCESS; if(pbSrc1) free(pbSrc1); if(pbSrc2) free(pbSrc2); if(pbFinal) free(pbFinal); //dbZoom=dbZoom+0.0070; //dbZoom=dbZoom+0.25; frame_num++; }//对应+=0.25倍数的for循环。 } else { _tprintf(_T("Fatal Error: GetModuleHandle failed\n")); nRetCode = 1; } getchar(); return nRetCode; } HRESULT Imagejoint(PBYTE pbSrc1,PBYTE pbSrc2,int iWidth,int iHeight,double dbZoom,PBYTE pbFinal,PBYTE pbMiddle1,PBYTE pbMiddle2) { double phase[33]={0};//16相位,包含端点存在33个距离 for (int i=0;i<33;i++) { double i2=1.0*i; phase[i]=fs(i2/16); } double count_a=0; double count_b=0; double count=0; double w=1; //Matlab中测试获取定值(34:541 -Y,41:728 -X),需要微调。 //int xl=41,xr=720,yu=34,yd=541;//原768*576大小图像中,存在内容的部分。 //int xl=3,xr=752,yu=3,yd=574; int xl=30,xr=720,yu=30,yd=550; int transition=25;//渐变像素过渡设置 //旋转中心为图像中心 double rx0=iWidth; double ry0=iHeight; double srcx,srcy,u,v; int xOr,yOr; int newWidth=ceil(dbZoom*iWidth); int newHeight=ceil(dbZoom*iHeight); int middleInFinalx=617;//内圈图像待放置的,处于目标图中的图像中心。(也是图像放大中心) int middleInFinaly=730; int changex=middleInFinalx-640; int changey=middleInFinaly-512; double scale_y=1.01; double scale_x=1.02;//0.9内圈拉开 for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { srcx=(double)(newWidth/2.0-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2.0-middleInFinaly+y)/(dbZoom) ; xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; int phasex=floor(16*u+0.5);//16相位 int phasey=floor(16*v+0.5); double A1,B1,C1,D1,A2,B2,C2,D2; A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; if( !(srcx>=xl && srcx<=xr && srcy>=yu && srcy<=yd))//越界部分需拼接为外圈大视场图像,远景 { //srcx=(double)(1.5*newWidth-640+x)/(3*dbZoom);//原始外图摆放位置,以目标图像中心为中心。 //srcy=(double)(1.5*newHeight-512+y)/(3*dbZoom); srcx=(double)(scale_x*1.5*newWidth-middleInFinalx+x+changex/0.7*dbZoom)/(scale_x*3*dbZoom);//补偏差 srcy=(double)(scale_y*1.5*newHeight-middleInFinaly+y+changey/0.7*dbZoom)/(scale_y*3*dbZoom);//此处映射公式为外圈比内圈放大倍数=3。原来是2。 xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; if(xOr>iWidth) xOr=iWidth; if(yOr>iHeight) yOr=iHeight; if(xOr<0) xOr=0; if(yOr<0) yOr=0; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle= pbSrc1[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc1[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc1[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc1[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc1[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+2)]*D1*D2; if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; pbFinal[y*1280+x]=pbSrc1[(yOr)*iWidth+(xOr)]; //pbFinal[y*1280+x]=255; } else if( !(srcx>=xl+transition && srcx<=xr-transition && srcy>=yu+transition && srcy<=yd-transition)) { double weight=1;//代表内圈所占的权重 if(srcx>=xl && srcx<=xl+transition) weight=(srcx-xl)*1.0/transition; else if(srcx>=xr-transition && srcx<=xr) weight=(xr-srcx)*1.0/transition; if(srcy>=yu && srcy<=yu+transition) weight=(srcy-yu)*1.0/transition; else if(srcy>=yd-transition && srcy<=yd) weight=(yd-srcy)*1.0/transition; if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yu && srcy<=yu+transition)) weight=min((srcx-xl),(srcy-yu))*1.0/transition; else if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yd-transition && srcy<=yd)) weight=min((srcx-xl),(yd-srcy))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yu && srcy<=yu+transition)) weight=min((xr-srcx),(srcy-yu))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yd-transition && srcy<=yd)) weight=min((xr-srcx),(yd-srcy))*1.0/transition; //pbFinal[y*1280+x]=255; srcx=(double)(scale_x*1.5*newWidth-middleInFinalx+x-35.7*dbZoom)/(scale_x*3*dbZoom);//补偏差 srcy=(double)(scale_y*1.5*newHeight-middleInFinaly+y+311.4*dbZoom)/(scale_y*3*dbZoom); xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; if(xOr>iWidth) xOr=iWidth; if(yOr>iHeight) yOr=iHeight; if(xOr<0) xOr=0; if(yOr<0) yOr=0; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle1= pbSrc1[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc1[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc1[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc1[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc1[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc1[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc1[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc1[(yOr+2)*iWidth+(xOr+2)]*D1*D2; if(middle1<=255&&middle1>=0) pbMiddle1[y*1280+x]=middle1; else if(middle1>255) pbMiddle1[y*1280+x]=255; else pbMiddle1[y*1280+x]=0; //外图的渐变区域的值,先存到pbMiddle1中。 //------------------------------------------------------------ srcx=(double)(newWidth/2-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2-middleInFinaly+y)/(dbZoom) ; xOr = floor(srcx); yOr = floor(srcy); u=srcx-xOr; v=srcy-yOr; phasex=floor(16*u+0.5);//16相位 phasey=floor(16*v+0.5); A1=phase[16+phasex]; B1=phase[phasex]; C1=phase[16-phasex]; D1=phase[32-phasex]; A2=phase[16+phasey]; B2=phase[phasey]; C2=phase[16-phasey]; D2=phase[32-phasey]; double middle2= pbSrc2[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc2[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc2[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc2[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc2[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+2)]*D1*D2; if(middle2<=255&&middle2>=0) pbMiddle2[y*1280+x]=middle2; else if(middle2>255) pbMiddle2[y*1280+x]=255; else pbMiddle2[y*1280+x]=0; //内图的渐变区域的值,再存到pbMiddle2中。 //count++; //count_a+=middle1; //count_b+=middle2; //w=count_a/count-count_b/count; //w=count_a/count_b; //边界融合 double middle3=(1-weight)* pbMiddle1[y*1280+x]+weight*pbMiddle2[y*1280+x]; pbFinal[y*1280+x]=middle3; } //内圈,核心区域pbSrc2-B else { double middle3= pbSrc2[(yOr-1)*iWidth+(xOr-1)]*A1*A2+ pbSrc2[(yOr)*iWidth+(xOr-1)]*A1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr-1)]*A1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr-1)]*A1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr)]*B1*A2+ pbSrc2[(yOr)*iWidth+(xOr)]*B1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr)]*B1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr)]*B1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+1)]*C1*A2+ pbSrc2[(yOr)*iWidth+(xOr+1)]*C1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+1)]*C1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+1)]*C1*D2+ pbSrc2[(yOr-1)*iWidth+(xOr+2)]*D1*A2+ pbSrc2[(yOr)*iWidth+(xOr+2)]*D1*B2+ pbSrc2[(yOr+1)*iWidth+(xOr+2)]*D1*C2+ pbSrc2[(yOr+2)*iWidth+(xOr+2)]*D1*D2; //w=count_a/count-count_b/count; //w=count_a/count_b;//0.762953 //middle3=middle3*w; if(middle3<=255&&middle3>=0) pbFinal[y*1280+x]=middle3; else if(middle3>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; } } } //亮度平衡部分 double sum1=0,sum2=0; double w2=1; double xl2=0,xr2=0,yu2=0,yd2=0; //四点用于确定内圈的亮度平衡范围 /* //xl2=ceil(xl*dbZoom-newWidth/2+640); //xr2=ceil(xr*dbZoom-newWidth/2+640); //yu2=ceil(yu*dbZoom-newHeight/2+512); //yd2=ceil(yd*dbZoom-newHeight/2+512); */ xl2=floor((xl+transition)*dbZoom-newWidth/2+middleInFinalx); xr2=ceil((xr-transition)*dbZoom-newWidth/2+middleInFinalx);//原来有细线是因为最后渐变部分2用的pbFinal yu2=floor((yu+transition)*dbZoom-newHeight/2+middleInFinaly); yd2=ceil((yd-transition)*dbZoom-newHeight/2+middleInFinaly); //for (int y=0;y<1024;y++) // { // for (int x=0;x<1280;x++) // { if(pbMiddle1[y*1280+x]!=205) // sum1+=pbMiddle1[y*1280+x]; // if(pbMiddle2[y*1280+x]!=205) // sum2+=pbMiddle2[y*1280+x]; // } // } // w2=sum1/sum2;//0.82 ,原来的直接取一个系数。 //统计直方图 double middle1_state[256]={0}; double middle2_state[256]={0}; int gray1=0; int gray2=0; int num1_L=0; int num1_H=0; int num2_L=0; int num2_H=0; int gray1L=0; int gray1H=0; int gray2L=0; int gray2H=0; for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { if(pbMiddle1[y*1280+x]!=205) { gray1=pbMiddle1[y*1280+x]; middle1_state[gray1]++;//按灰度级统计外圈的 } if(pbMiddle2[y*1280+x]!=205) { gray2=pbMiddle2[y*1280+x]; middle2_state[gray2]++;//按灰度级统计内圈的 } } } //统计好后分别找前1/3和后1/3 //先统计总个数 for(int gray=0;gray<256;gray++) { sum1+=middle1_state[gray];//个数之和,共有多少个有效元素。 sum2+=middle1_state[gray]; } //外圈统计中找1/3 for(int gray=0;gray<256;gray++) { num1_L+=middle1_state[gray]; if(num1_L<=sum1/3.0) {gray1L=gray;}//前1/3数量的灰度级是到gray1L。 else ; } for(int gray=255;gray>=0;gray--) { num1_H+=middle1_state[gray]; if(num1_H<=sum1/3.0) {gray1H=gray;}//后1/3数量的灰度级是到gray1H。 else ; } //内圈统计找1/3 for(int gray=0;gray<256;gray++) { num2_L+=middle2_state[gray]; if(num2_L<=sum2/3.0) {gray2L=gray;}//前1/3数量的灰度级是到gray2L。 else ; } for(int gray=255;gray>=0;gray--) { num2_H+=middle2_state[gray]; if(num2_H<=sum2/3.0) {gray2H=gray;}//后1/3数量的灰度级是到gray2H。 else ; } //统计好后,计算A1,A2,B1,B2。双点进行亮度平衡。 double sum1L=0,sum1H=0,sum2L=0,sum2H=0;//用于统计个数 double pix_sum1L=0,pix_sum1H=0,pix_sum2L=0,pix_sum2H=0;//用于累计像素值求和 double A1=0,A2=0,B1=0,B2=0; double w3=1,b3=1;//要用到的,增益和偏置参数 //外圈的1/3计算A1,A2 for(int gray=0;gray<=gray1L;gray++) { sum1L+=middle1_state[gray]; pix_sum1L+=middle1_state[gray]*gray; } for(int gray=255;gray>=gray1H;gray--) { sum1H+=middle1_state[gray]; pix_sum1H+=middle1_state[gray]*gray; } //内圈的1/3计算B1,B2 for(int gray=0;gray<=gray2L;gray++) { sum2L+=middle2_state[gray]; pix_sum2L+=middle2_state[gray]*gray; } for(int gray=255;gray>=gray2H;gray--) { sum2H+=middle2_state[gray]; pix_sum2H+=middle2_state[gray]*gray; } A1=pix_sum1L/sum1L; A2=pix_sum1H/sum1H; B1=pix_sum2L/sum2L; B2=pix_sum2H/sum2H; w3=(A2-A1)/(B2-B1); b3=A1-w3*B1; double middle=0; //w3=1;b3=0; //=================================================================================== //亮度平衡 for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { if(x>=xl2 && x<=xr2 && y>=yu2 && y<=yd2) { double middle=0; middle=w3*pbFinal[y*1280+x]+b3; //middle=w2*pbFinal[y*1280+x]; if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle ; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; } } } //对渐变范围也做平衡处理: for (int y=0;y<1024;y++) { for (int x=0;x<1280;x++) { srcx=(double)(newWidth/2.0-middleInFinalx+x)/dbZoom; srcy=(double)(newHeight/2.0-middleInFinaly+y)/(dbZoom); if( !(srcx>xl && srcx<xr && srcy>yu && srcy<yd)) ;//外圈保持不变 else if( !(srcx>=xl+transition && srcx<=xr-transition && srcy>=yu+transition && srcy<=yd-transition)) { double weight=1;//代表内圈所占的权重 if(srcx>=xl && srcx<=xl+transition) weight=(srcx-xl)*1.0/transition; else if(srcx>=xr-transition && srcx<=xr) weight=(xr-srcx)*1.0/transition; if(srcy>=yu && srcy<=yu+transition) weight=(srcy-yu)*1.0/transition; else if(srcy>=yd-transition && srcy<=yd) weight=(yd-srcy)*1.0/transition; if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yu && srcy<=yu+transition)) weight=min((srcx-xl),(srcy-yu))*1.0/transition; else if((srcx>=xl && srcx<=xl+transition)&&(srcy>=yd-transition && srcy<=yd)) weight=min((srcx-xl),(yd-srcy))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yu && srcy<=yu+transition)) weight=min((xr-srcx),(srcy-yu))*1.0/transition; else if((srcx>=xr-transition && srcx<=xr)&&(srcy>=yd-transition && srcy<=yd)) weight=min((xr-srcx),(yd-srcy))*1.0/transition; double middle=0; //middle=255; middle=(1-weight)*pbMiddle1[y*1280+x]+weight*(w3*pbMiddle2[y*1280+x]+b3); //middle=(1-weight)*pbMiddle1[y*1280+x]+weight*(w2*pbMiddle2[y*1280+x]); if(middle<=255&&middle>=0) pbFinal[y*1280+x]=middle ; else if(middle>255) pbFinal[y*1280+x]=255; else pbFinal[y*1280+x]=0; } } } return ERROR_SUCCESS; }