图片的二次线性缩放

项目需要,要截图屏幕图片,并缩放1/4显示,使用已有的方式,缩小的效果不好,要用二次线性,在网络上找了一个算法加以修改,得到可接受的图像。代码如下:

采用浮点数运算可以得到比较好的效果,

而定点数,得到的效果比较差,用公司内部的定点数方式,得到的效果有所改善,但与浮点数效果还是有差距,感觉是取的定点数不是最合适的,谁有更好的取得定点数的方式可以分享一下。

#if 1  //浮点数的二次线性缩放
void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe);
void Bilinear0(SFNColor* pic,double fx,double fy,int width,SFNColor* result);
#else  //定点数的二次线性缩放,但是定点数没有取好,导致图像模糊严重,所以才要浮点数的
void Bilinear0(SFNColor* pic,long fx,long fy,int width,SFNColor* result);
void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe);
#endif

#if 1
void Bilinear0(SFNColor* pic,double fx,double fy,int width,SFNColor* result)
{
    long x= (long)fx;
    long y=(long)fy;
    if (x>fx)
         --x;
    //x=floor(fx);
    if (y>fy)
        --y;
    //y=floor(fy);
    {
        SFNColor Color0=pic[y * width + x];
        SFNColor Color2=pic[y * width + x+1];
        SFNColor Color1=pic[(y+1) * width + x];
        SFNColor Color3=pic[(y +1)* width + (x+1)];

        double u=fx-x;
        double v=fy-y;
        double pm3=u*v;
        double pm2=u*(1-v);
        double pm1=v*(1-u);
        double pm0=(1-u)*(1-v);

        SFInt8 R=(pm0*(Color0>>11)+pm1*(Color1>>11)+pm2*(Color2>>11)+pm3*(Color3>>11));//(Color0>>11);//
        SFInt8 G=(pm0*((Color0&0x07E0)>> 5)+pm1*((Color1&0x07E0)>> 5)+pm2*((Color2&0x07E0)>> 5)+pm3*((Color3&0x07E0)>> 5));//(Color0&0x07E0)>> 5;//
        SFInt8 B=(pm0*((Color0&0x001F))+pm1*((Color1&0x001F))+pm2*((Color2&0x001F))+pm3*((Color3&0x001F)));//(Color0&0x001F);//
        *result = (R<<11)|(G<<5)|B;
    }
   
}

 void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe)
{
    SFNColor* pDstLine = pDestBuf;
    long y=0;
    for ( y=0;y<nDestHe;++y)
    {
        long x=0;
        double srcy=(y+0.4999999)*nSrcHe/nDestHe-0.5;
        if(srcy<0)srcy = 0;
       
        for ( x=0;x<nDestWi;++x)
        {
            double srcx=(x+0.4999999)*nSrcWi/nDestWi-0.5;
            if(srcx<0)srcx = 0;
            Bilinear0(pSrcBuf,srcx,srcy,nSrcWi,&pDstLine[x]);
        }
        pDstLine += nDestWi;
    }
}
#else
void Bilinear0(SFNColor* pic,long fx,long fy,int width,SFNColor* result)
{
    long x=fx >> 16; //if (x>fx) --x; x=floor(fx);  
    long y=fy >> 16;// if (y>fy) --y; y=floor(fy);

    SFUint16 Color0=pic[y * width + x];
    SFUint16 Color2=pic[y * width + x+1];
    SFUint16 Color1=pic[(y+1) * width + x];
    SFUint16 Color3=pic[(y +1)* width + (x+1)];

    SFUint32 u_8=(fx & 0xFFFF)>>8;
    SFUint32 v_8=(fy & 0xFFFF)>>8;
    SFUint32 pm3=(u_8*v_8);
    SFUint32 pm2=(u_8*(SFUint32)(256-v_8));
    SFUint32 pm1=(v_8*(SFUint32)(256-u_8));
    SFUint32 pm0=((256-u_8)*(256-v_8));

    SFUint8 R=(pm0*((Color0&0xF800)>>11)+pm1*((Color1&0xF800)>>11)+pm2*((Color2&0xF800)>>11)+pm3*((Color3&0xF800)>>11))>>16;//(Color0>>11);//
    SFUint8 G=(pm0*((Color0&0x07E0)>> 5)+pm1*((Color1&0x07E0)>> 5)+pm2*((Color2&0x07E0)>> 5)+pm3*((Color3&0x07E0)>> 5))>>16;//(Color0&0x07E0)>> 5;//
    SFUint8 B=(pm0*((Color0&0x001F))+pm1*((Color1&0x001F))+pm2*((Color2&0x001F))+pm3*((Color3&0x001F)))>>16;//(Color0&0x001F);//
 
    *result = (R<<11)|(G<<5)|B;
}

extern const SFUint16 _xs_fast_div_table_i16[513];
 SFInt32 fx32divi(SFInt32 a, int b)  //定点数除法,用这个方式,显示效果有所改善
{
    if(!a)
    {
        return 0;
    }
    else if(b>=-512 && b<=512)
    {
        if(b<0)
        {
            return (SFInt32)(((SFInt64)a*(-(int)_xs_fast_div_table_i16[-b]))>>16);
        }
        else
        {
            return (SFInt32)(((SFInt64)a*((int)_xs_fast_div_table_i16[b]))>>16);
        }
    }
    else
    {
        return (SFInt32)(a/b);
    }
}

 void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe)
{
    //int nSrcX = 0,nSrcY= 0;
    long srcy=0;
    long y=0;
    SFNColor* pDstLine = pDestBuf;
    //SFUint64 nSrcXStep = nSrcWi / (float)nDestWi * (1<<16);
    //SFUint64 nSrcYStep = nSrcHe / (float)nDestHe* (1<<16);
    //long nSrcXStep = fx32div(nSrcWi<<16,nDestWi<<16);
    //long nSrcYStep = fx32div(nSrcHe<<16,nDestHe<<16);
   // sf_dbgprintf(L"_______nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);

    /*long nSrcXStep = fx32divi(nSrcWi<<16,nDestWi);
    long nSrcYStep = fx32divi(nSrcHe<<16,nDestHe);*/
    long nSrcXStep = (nSrcWi<<16)/nDestWi;
    long nSrcYStep = (nSrcHe<<16)/nDestHe;
    //sf_dbgprintf(L"_______nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);
    if (nSrcXStep > nSrcYStep)
    {
        nSrcXStep = nSrcYStep;
    }
    else
    {
        nSrcYStep = nSrcXStep;
    }
    //sf_dbgprintf(L"___222____nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);
    for ( y=0;y<nDestHe;++y)
    {
        long srcx=0;
        long x=0;
        for ( x=0;x<nDestWi;++x)
        {
            Bilinear0(pSrcBuf,srcx,srcy,nSrcWi,&pDstLine[x]);
            srcx += nSrcXStep;
        }
        srcy += nSrcYStep;
        pDstLine += nDestWi;
    }
}
#endif

 

### VisionPro 中二次线性变换缩放的实现方法 在 VisionPro 的框架下,二次线性变换通常用于校正图像中的几何失真或调整图像的比例关系。这种变换可以通过矩阵运算来完成,其中涉及到仿射变换(Affine Transformation)或者更复杂的投影变换(Projective Transformation)。以下是关于如何在 VisionPro 中实现二次线性变换缩放的具体说明: #### 1. 基本原理 二次线性变换可以被理解为一种组合操作,它先应用一线性变换(如旋转、平移),然后再叠加另一线性变换(如缩放)。这两变换通过矩阵乘法的方式结合起来[^1]。 假设原始图像经过第一线性变换 \( T_1 \),其对应的变换矩阵表示为: \[ T_1 = \begin{bmatrix} a & b \\ c & d \end{bmatrix} \] 第二次线性变换 \( T_2 \) 主要负责缩放操作,其变换矩阵可定义为: \[ T_2 = \begin{bmatrix} s_x & 0 \\ 0 & s_y \end{bmatrix} \] 其中 \( s_x, s_y \) 是分别沿 X 和 Y 方向的缩放因子。 最终的整体变换矩阵 \( T_{final} \) 可由这两个矩阵相乘得到: \[ T_{final} = T_2 \cdot T_1 = \begin{bmatrix} s_x a & s_x b \\ s_y c & s_y d \end{bmatrix} \] 此过程可通过 VisionPro 提供的相关 API 或者自定义脚本来实现。 #### 2. 使用 VisionPro 工具链 VisionPro 支持多种内置工具来进行图像变换的操作。例如,在非线性模式下的工具会自动提取网格点并计算二维线性变换和非线性变换。如果目标仅限于简单的缩放,则可以直接利用这些预设的功能模块。 对于特定需求——即需要手动控制每线性变换的过程,可能需要用到 CogCreateLineBisectPointsTool 来辅助定位特征点的位置,并基于这些点构建所需的变换逻辑[^2]。 #### 3. 自定义代码示例 当现有工具无法满足复杂场景的需求时,开发者可以选择编写自定义 Python 脚本来调用 OpenCV 库或其他第三方库执行精确的矩阵运算。下面是一个基本的例子展示如何运用 NumPy 构建上述提到的复合变换矩阵并应用于一张图片上: ```python import numpy as np import cv2 def apply_transform(image, scale_x=1.0, scale_y=1.0): rows, cols = image.shape[:2] # 定义初始旋转变换 (作为第一个线性变换) theta = np.radians(30) # 示例角度 cos_theta = np.cos(theta) sin_theta = np.sin(theta) t1_matrix = np.array([[cos_theta, -sin_theta], [sin_theta, cos_theta]]) # 定义第二个线性变换: 缩放 t2_matrix = np.diag([scale_x, scale_y]) final_matrix = np.dot(t2_matrix, t1_matrix).astype(np.float32) transformed_image = cv2.warpAffine( src=image, M=np.vstack([final_matrix.T, [0, 0]]), dsize=(cols * int(scale_x), rows * int(scale_y)) ) return transformed_image if __name__ == "__main__": img = cv2.imread('example.jpg') result_img = apply_transform(img, scale_x=1.5, scale_y=0.75) cv2.imwrite('transformed_example.jpg', result_img) ``` 以上代码片段实现了对输入图像的一简单旋转加各方向独立缩放的效果。 #### 结论 综上所述,无论是借助 VisionPro 内置的强大功能还是开发专属解决方案,都可以有效地达成二次线性变换中的缩放目的。具体采用哪种途径取决于实际应用场景的要求以及个人技术偏好。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值