拼接备忘(随笔记)

 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
"));
                nRetCode = 1;
                
            }
            //Load 图像到cImage对象中
            hResult1=cImage_far.Load(filename1);
            hResult2=cImage_near.Load(filename2);
            if(hResult1!=ERROR_SUCCESS||hResult2!=ERROR_SUCCESS)
            {
                _tprintf(_T("源图像文件名错误!
"));
                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("内存申请错误!
"));
                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("图像处理错误!
"));
                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("图像结果保存错误!
"));
                nRetCode= -5;
               
            }
            _tprintf(_T("图像处理成功!
"));
            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
"));
        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;
}
View Code

为什么选择(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
"));
                nRetCode = 1;
                
            }
            //Load 图像到cImage对象中
            hResult1=cImage_far.Load(filename1);
            hResult2=cImage_near.Load(filename2);
            if(hResult1!=ERROR_SUCCESS||hResult2!=ERROR_SUCCESS)
            {
                _tprintf(_T("源图像文件名错误!
"));
                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("内存申请错误!
"));
                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("图像处理错误!
"));
                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("图像结果保存错误!
"));
                nRetCode= -5;
               
            }
            _tprintf(_T("图像处理成功!
"));
            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
"));
        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;
}
View Code
原文地址:https://www.cnblogs.com/wxl845235800/p/11210449.html