原创 李现路:DSP6000图像位移与变形典型算法

2009-12-12 17:35 1240 1 1 分类: 处理器与DSP

李现路:DSP6000图像位移与变形典型算法
一、图像的平移算法
图像平移的数学表达式原理:
初始坐标为(x0,y0)的点经过平移(tx,ty)(以向右,向下为正方向)后,坐标变为(x1,y1)。这两点之间的关系是x1=x0+tx,y1=y0+ty 。
这样,平移后的图像上的每一点都可以在原图像中找到对应的点。例如,对于新图中的(0,0)像素,代入上面的议程组,可以求出对应原图中的点,可以直接将它的像素值同意设置为0或者255(对于灰度图就是黑色或白色)。
同样,若有点不在原图中,也就说明原图中有点被移出显示区域。如果不想丢失被移出的部分图像,可以将新生成的图像扩大tx,高度扩大ty。


平移处理的C语言代码:


/*图像偏移量初始化*/
Int intXOffset="-200"; //水平偏移量
Int intYOffset="-200"; //垂直偏移量,必须是2的整数
void geometryTrans()
{
 int i,j;
 int intCapX,intCapY;
 for(i=0;i<numLines;i++) //行数
 {
     for(j=0;j<numPixels;j++) //像素数 /每行
     {             
            intCapX = j-intXOffset;
            intCapY = i-intYOffset/2;           
            
            // 判断 是否在原图范围内
            if((intCapX>=0) && (intCapX<numPixels))  
            {  
                //奇数行
             if((i<numLines/2) && (intCapY>=0) && (intCapY<numLines/2))
             {
        // 传送亮度信号
        *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + (i-intYOffset/2)*numPixels + intCapX); 
       }
       //偶数行
       else if((i>=numLines/2) && (i<numLines) && (intCapY>=numLines/2) && (intCapY<numLines))
       {
      // 传送亮度信号
        *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + (i-intYOffset/2)*numPixels + intCapX);       
       }
       else
       {
           *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
       }                                                       
         }
            else
            {
              *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
            }                         
  } 
 }

二、图像的垂直镜像变换算法
数学表达式原理:
设图像高度为IHeight,宽度为IWidth,原图中(x0,y0)垂直镜像后将变为(x0,
IHeight-y0),其表达式为:
设图像高度为IHeight,宽度为IWidth,原图中(x0,y0)垂直镜像后将变为(x0,
IHeight-y0),其表达式为:
X0=x1; y0=IHeight-y1


算法的C语言代码:


 portNumber = 0;
 vpHchannel0 = bt656_8bit_ncfc(portNumber);
 bt656_capture_start(vpHchannel0);
 /*等待第一帧数据采集完成*/
 while(capNewFrame == 0){}
 /*将数据存入显示缓冲区,并清采集完成的标志*/
 capNewFrame =0;


 for(i=0;i<numLines;i++)
 {
     /*传送Y缓冲区*/
     //前半部分为原始图像
  DAT_copy((void *)(capYbuffer + i * numPixels),
              (void *)(disYbuffer + i * numPixels),
              numPixels>>1);
  //后半部分为垂直镜像图像
  DAT_copy((void *)(capYbuffer + i * numPixels),
         (void *)(disYbuffer + (numPixels>>1) + (numLines-1-i) * numPixels),
         numPixels>>1);
                 
     /*传送Cb缓冲区*/
     //前半部分为原始图像
     DAT_copy((void *)(capCbbuffer + i * (numPixels >> 1)),
              (void *)(disCbbuffer + i * (numPixels >> 1)),
              numPixels>>2);
     //后半部分为垂直镜像图像
        DAT_copy((void *)(capCbbuffer + i * (numPixels >> 1)),
                 (void *)(disCbbuffer + (numPixels>>2) + (numLines-1-i) * (numPixels >> 1)),
                 numPixels>>2);               
             
             
  /*传送Cr缓冲区*/
  //前半部分为原始图像
     DAT_copy((void *)(capCrbuffer + i * (numPixels >> 1)),
              (void *)(disCrbuffer + i * (numPixels >> 1)),
              numPixels>>2);
     //后半部分为垂直镜像图像        
     DAT_copy((void *)(capCrbuffer + i * (numPixels >> 1)),
              (void *)(disCrbuffer + (numPixels>>2) + (numLines-1-i) * (numPixels >> 1)),
              numPixels>>2);   
  } 
 
 
 /*启动显示模块*/
 bt656_display_start(vpHchannel1);
 /*建立显示的实时循环*/
 for(;;)
 {
  /*当采集区的数据已经采集好,而显示缓冲区的数据已空*/
  if((capNewFrame == 1)&&(disNewFrame == 1))
  {
   /*将数据装入显示缓冲区,并清采集完成的标志*/
   capNewFrame =0;
   disNewFrame =0;
   for(i=0;i<numLines;i++)
   {
       /*传送Y缓冲区*/
       //前半部分为原始图像
    DAT_copy((void *)(capYbuffer + i * numPixels),
                (void *)(disYbuffer + i * numPixels),
                numPixels>>1);
    //后半部分为垂直镜像图像
    DAT_copy((void *)(capYbuffer + i * numPixels),
              (void *)(disYbuffer + (numPixels>>1) + (numLines-1-i) * numPixels),
              numPixels>>1);
                      
       /*传送Cb缓冲区*/
       //前半部分为原始图像
       DAT_copy((void *)(capCbbuffer + i * (numPixels >> 1)),
                (void *)(disCbbuffer + i * (numPixels >> 1)),
                numPixels>>2);
       //后半部分为垂直镜像图像
          DAT_copy((void *)(capCbbuffer + i * (numPixels >> 1)),
                   (void *)(disCbbuffer + (numPixels>>2) + (numLines-1-i) * (numPixels >> 1)),
                   numPixels>>2);               
               
               
    /*传送Cr缓冲区*/
    //前半部分为原始图像
       DAT_copy((void *)(capCrbuffer + i * (numPixels >> 1)),
                (void *)(disCrbuffer + i * (numPixels >> 1)),
                numPixels>>2);
       //后半部分为垂直镜像图像        
       DAT_copy((void *)(capCrbuffer + i * (numPixels >> 1)),
                (void *)(disCrbuffer + (numPixels>>2) + (numLines-1-i) * (numPixels >> 1)),
                numPixels>>2);   
    }
  }
 } 
}
三、图像的水平镜像变换算法
数学表达式原理:


设图像高度为IHeight,宽度为IWidth,原图中(x0,y0)经过水平镜像后从未将变为
(IWidth-x0,y0),其表达式为:
X0=IWidth-y1; y0=y1


算法的C语言代码:


/*水平镜像变换处理*/
void horizTranspose()
{
 int i,j;
 for(i=0;i<numLines;i++)
 {     
     /*前半部分为原始图像*/
     //传送临时Y缓冲区
  DAT_copy((void *)(capYbuffer + i * numPixels),
              (void *)(tempYbuffer + i * numPixels),
              numPixels>>1);                        
     //传送临时Cb缓冲区
     DAT_copy((void *)(capCbbuffer + i * (numPixels >> 1)),
              (void *)(tempCbbuffer + i * (numPixels >> 1)),
              numPixels>>2);        
     //传送临时Cr缓冲区
     DAT_copy((void *)(capCrbuffer + i * (numPixels >> 1)),
              (void *)(tempCrbuffer + i * (numPixels >> 1)),
              numPixels>>2);                                            
  
  /*后半部分为水平镜像图像*/
  for(j=numPixels/2;j<numPixels;j++)
  {
   //传送临时Y缓冲区  
   *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + i*numPixels + numPixels-1-j);   
  }
      
     for(j=(numPixels>>2);j<(numPixels>>1);j++)
  {
   //传送临时Cb缓冲区
   *(Uint8 *)(tempCbbuffer + i*(numPixels>>1) + j) = *(Uint8 *)(capCbbuffer + i*(numPixels>>1) + (numPixels>>1)-1-j);   
   //传送临时Cr缓冲区
   *(Uint8 *)(tempCrbuffer + i*(numPixels>>1) + j) = *(Uint8 *)(capCrbuffer + i*(numPixels>>1) + (numPixels>>1)-1-j);   
  }
    
  }
}



四、图像的缩放算法
数学表达式原理:
假设图像x轴方向缩放比率fx,y轴方向缩放比率是fy,那么原图中点(x0,y0)对应
于新图中的点(x1,y1)的转换表达式为:
X0=x1/fx; y0=y1/fy


算法的C语言代码:
 
/*图像缩放参数*/
Float fXZoomRatio="0".5; //水平缩放比率
Float fYZoomRatio="0".5; //垂直缩放比率
/*缩放处理函数*/


/*缩放处理*/
void zoom()
{
 int i,j;
 int intCapX,intCapY;
 for(i=0;i<numLines;i++)
 {
     for(j=0;j<numPixels;j++)
     {             
            intCapX = (int)(j/fYZoomRatio+0.5);
            intCapY = (int)(i/fXZoomRatio+0.5);          
            
            //判断是否在原图范围内
            if((intCapX>=0) && (intCapX<numPixels))  
            {  
             if((i<numLines/2) && (intCapY>=0) && (intCapY<numLines/2))
             {
        //传送亮度信号
        *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + intCapY*numPixels + intCapX); 
       }
       else if((i>=numLines/2) && (i<numLines) && (intCapY>=numLines/2) && (intCapY<numLines))
       {
      //传送亮度信号
        *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + intCapY*numPixels + intCapX);       
       }
       else
       {
           *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
       }                                                       
         }
            else
            {
              *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
            }                         
  } 
 }
}


五、图像的旋转实验


数学表达式原理:


下面我们来推导一下旋转运算的变换公式。如下图所示,点(x0,y0)经过旋转θ度后
坐标变成(x1,y1)。其数学表达式为:
X0=x1cos(θ)+y1sin(θ)+ccos(θ)-dsin(θ)+a ;
Y0=-xsin(θ)+y1cos(θ)+csin(θ)-dcos(θ)+ b


算法的C语言代码:


/*图像旋转参数*/
Float fAngle="3".1415927/3; //旋转的角度
*画矩形边框函数*/
Void drawRectangle();
*计算图像旋转参数*/
Void computeParameter();
/*进行图像旋转处理*/
void rotate()
{
 int i,j,intInc;
 int intCapYInc;
 int intCapX,intCapY;
 
 /*进行图像旋转,重新赋值*/
 //方框内奇数行
 for(i=intALines;i<intDLines;i++)
 {
     for(j=intAPixels;j<intDPixels;j++)
     {
            intInc = i*2;  


            intCapX    = (int)(j*cosAngle + intInc*sinAngle + f1 + 0.5);
            intCapYInc = (int)(intInc*cosAngle - j*sinAngle + f1 + 0.5);          
                     
            if((intCapYInc%2)==0)
            {
             intCapY = intCapYInc/2;
            }
            else
            {
             intCapY = (intCapYInc-1)/2+numLines/2;
            }
            
            //判断是否在原图范围内
            if((intCapX>=0) && (intCapX<numPixels) && (intCapY>=0) && (intCapY<numLines))  
            {
       //传送亮度信号
       *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + intCapY*numPixels + intCapX);                                                       
         }
            else
            {
              *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
            }
       
  } 
 }
   
 //方框内偶数行
 for(i=numLines/2+intALines;i<numLines/2+intDLines;i++)
 {
     for(j=intAPixels;j<intDPixels;j++)
     {  
            intInc = (i-numLines/2)*2 + 1;


            intCapX    = (int)(j*cosAngle + intInc*sinAngle + f1 + 0.5);
            intCapYInc = (int)(intInc*cosAngle - j*sinAngle + f1 + 0.5);          
                     
            if((intCapYInc%2)==0)
            {
             intCapY = intCapYInc/2;
            }
            else
            {
             intCapY = (intCapYInc-1)/2+numLines/2;
            }            


            //判断是否在原图范围内
            if((intCapX>=0) && (intCapX<numPixels) && (intCapY>=0) && (intCapY<numLines))  
            {
       //传送亮度信号
       *(Uint8 *)(tempYbuffer + i*numPixels + j) = *(Uint8 *)(capYbuffer + intCapY*numPixels + intCapX);                                                       
         }
            else
            {
              *(Uint8 *)(tempYbuffer + i*numPixels + j) = 0xFF;
            }
               
  } 
 } 
}


 


完整版本请见http://www.51qianru.cn/bbs/


                                              曙海教育


                                            曙海嵌入式学院


                        (课程:DSP培训,FPGA培训,MTK培训,Android培训,iPhone培训)


                                           电话:021-51875830


                                           网址:http://www.51qianru.cn


                                              讲师:李现路


                          版权所有-曙海教育 欢迎转摘,转摘请注明作者和出处

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
1
关闭 站长推荐上一条 /3 下一条