首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 怎么把旋转和缩放处理的两个独立的的循环合并成一个循环,同时处理呢? [已结贴,结贴人:ljooo]
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ljooo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 揭贴率:
    发表于:2008-08-08 09:20:13 楼主
    旋转和缩放都用最邻近的一个坐标点代替,会产生误差,其中一个误差是转换后的坐标一般是小数的,小数取整会失真。
    我想让他们合并,那么原来需要两次的小数取整,合并后只需要一次。


    //   缩放时,计算该象素在源DIB中的坐标
    i0   =   (LONG)   (i   /   fYZoomRatio   +   0.5);
    j0   =   (LONG)   (j   /   fXZoomRatio   +   0.5);


    //   旋转时,计算该象素在源DIB中的坐标
    i0   =   LONG(-((float)   j)   *   fSina   +   ((float)   i)   *   fCosa   +   f2+0.5);
    j0   =     LONG(((float)   j)   *   fCosa   +   ((float)   i)   *   fSina   +   f1+0.5);

    我这样合并
    //   计算该象素在源DIB中的坐标
    i0   =     i   /   fYZoomRatio   ;
    j0   =     j   /   fXZoomRatio   ;
    i1   =   LONG(-((float)   j0)   *   fSina   +   ((float)   i0)   *   fCosa   +   f2+0.5);
    j1   =     LONG(((float)   j0)   *   fCosa   +   ((float)   i0)   *   fSina   +   f1+0.5);

    但结果是错误的,图片已经变成一些没有意义的像素点了。

    请问要怎样合并?
    100  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • sunyim
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 09:27:091楼 得分:10
    不能合并
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • cnzdgs
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    • 5

      2

      13

    发表于:2008-08-08 09:31:292楼 得分:20
    把i0、j0定义为float型试试。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ljooo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 09:37:053楼 得分:0
    把i0、j0定义为float型试试。

    没用。整个图片的图案都是没有意义的了。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • Show_Mike
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 09:39:224楼 得分:30
    图片变成没有意义的像素点的原因在于相位信息的丢失.你合并的模型及时精度没有提高,反而下降了:你的j0中的0.5处理不当,应该想法累积到j1中去,而不是简单地加上一个0.5就可以了!
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ljooo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 10:02:175楼 得分:0
    我知道要把i0,j0改成float。
    问题是图片变得不可识别,那就是说整个方法都是错误的。


    下面的源代码,我的代码风格不好。

    我把bmp的数据赋给了c类型的字符串lpDIBBits了(这个修改可能会引起大家的困惑),目的是减少指针操作。原来的宽度和高度lWidth,lHeight。旋转的分别为lNewWidth,lNewHeight。缩放的为lNewWidth2,lNewHeight2。
    要旋转的角度是 iRotateAngle,已经是弧度了。


    原来的操作,代码是没有问题的。不过我在记事本里改了一下变量名和注释,可能会引进小的错误。

    //图像旋转

    // 旋转后图像的宽度和高度
    int lNewWidth;
    int lNewHeight;
    // 旋转角度(弧度)
    float fRotateAngle;
    // 旋转角度的正弦和余弦
    float fSina, fCosa;
    // 两个中间常量
    float f1,f2;
    // 象素在源DIB中的坐标
    LONG i0;
    LONG j0;
    // 源图四个角的坐标(以图像中心为坐标系原点)
    float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
    // 旋转后四个角的坐标(以图像中心为坐标系原点)
    float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
    // 将旋转角度从度转换到弧度
    fRotateAngle=(float)iRotateAngle;
    // 计算旋转角度的正弦
    fSina = (float) sin((double)fRotateAngle);
    // 计算旋转角度的余弦
    fCosa= (float) cos((double)fRotateAngle);
    // 计算原图的四个角的坐标(以图像中心为坐标系原点)
    fSrcX1 = (float) (- (lWidth  - 1) / 2);
    fSrcY1 = (float) (  (lHeight - 1) / 2);
    fSrcX2 = (float) (  (lWidth  - 1) / 2);
    fSrcY2 = (float) (  (lHeight - 1) / 2);
    fSrcX3 = (float) (- (lWidth  - 1) / 2);
    fSrcY3 = (float) (- (lHeight - 1) / 2);
    fSrcX4 = (float) (  (lWidth  - 1) / 2);
    fSrcY4 = (float) (- (lHeight - 1) / 2);

    // 计算新图四个角的坐标(以图像中心为坐标系原点)
    fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
    fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
    fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
    fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
    fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
    fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
    fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
    fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;


    // 计算旋转后的图像实际宽度
    lNewWidth  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
    // 计算旋转后的图像高度
    lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);

    unsigned char *lpNewBits=new unsigned char[ lNewWidth* lNewHeight];

    // 两个常数,这样不用以后每次都计算了
    f1  =  (float)  (-0.5  *  (lNewWidth  -  1)  *  fCosa  -  0.5  *  (lNewHeight  -  1)  *  fSina 
    +  0.5  *  (lWidth    -  1)); 
    f2  =  (float)  (  0.5  *  (lNewWidth  -  1)  *  fSina  -  0.5  *  (lNewHeight  -  1)  *  fCosa 
    +  0.5  *  (lHeight  -  1)); 

    // 针对图像每行进行操作
    for(int i = 0; i < lNewHeight; i++)
    {
    // 针对图像每列进行操作
    for(int j = 0; j < lNewWidth; j++)
    {
    // 计算该象素在源DIB中的坐标
    i0 = LONG(-((float) j) * fSina + ((float) i) * fCosa + f2+0.5);
    j0 =  LONG(((float) j) * fCosa + ((float) i) * fSina + f1+0.5);


    if( (i0 >= 0) || (j0 < lWidth ) || (j0 >= 0) || (i0 < lHeight )) 
    {
    // 要计算的点在源图范围内
    lpNewBits[lNewWidth* (i) +j]=lpDIBBits[lWidth*(i0)+j0];

    }
    else
    // 要计算的点不在源图范围内,直接返回255。
    lpNewBits[lNewWidth*(i)+j]=255;

    }

    }


    //图像缩放

    //缩放比例
    float fXZoomRatio;
    float fYZoomRatio;
    fXZoomRatio=0.5f;
    fYZoomRatio=0.5f;

    // 缩放后图像的宽度和高度
    LONG lNewWidth2;
    LONG lNewHeight2;

    //// 计算缩放后的图像实际宽度
    lNewWidth2 = (LONG) (lNewWidth * fXZoomRatio + 0.5);

    //// 计算缩放后的图像高度
    lNewHeight2 = (LONG) (lNewHeight * fYZoomRatio + 0.5);

    unsigned char *lpNewBits2=new unsigned char[ lNewWidth2* lNewHeight2];
    for(int i = 0; i < lNewHeight2; i++)
    {
    // 针对图像每列进行操作
    for(int j = 0; j < lNewWidth2; j++)
    {

    // 计算该象素在源DIB中的坐标
    i0 = (LONG) (i / fYZoomRatio + 0.5);
    j0 = (LONG) (j / fXZoomRatio + 0.5);

    // 判断是否在源图范围内
    if( (j0 >= 0) && (j0 < lNewHeight) && (i0 >= 0) && (i0 < lNewHeight))
    {
    lpNewBits2[lNewWidth2*( lNewHeight2-1-i)+j]=lpNewBits[lNewWidth*( lNewHeight-1-i0)+j0];

    }
    else
    {
    // 对于源图中没有的象素,直接赋值为255
    lpNewBits2[lNewWidth2*( lNewHeight2-1-i)+j] = 255;
    }
    }
    }


    合并的情况


    //图像旋转

    // 旋转后图像的宽度和高度
    int lNewWidth;
    int lNewHeight;

    // 旋转角度(弧度)
    float fRotateAngle;

    // 旋转角度的正弦和余弦
    float fSina, fCosa;
    // 两个中间常量
    float f1,f2;
    // 象素在源DIB中的坐标
    LONG i0;
    LONG j0;

    // 源图四个角的坐标(以图像中心为坐标系原点)
    float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;

    // 旋转后四个角的坐标(以图像中心为坐标系原点)
    float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;

    // 将旋转角度从度转换到弧度

    // fRotateAngle = (float) (iRotateAngle*3.1415926535/180);
    fRotateAngle=(float)iRotateAngle;
    // 计算旋转角度的正弦
    fSina = (float) sin((double)fRotateAngle);

    // 计算旋转角度的余弦
    fCosa= (float) cos((double)fRotateAngle);

    // 计算原图的四个角的坐标(以图像中心为坐标系原点)
    fSrcX1 = (float) (- (lWidth  - 1) / 2);
    fSrcY1 = (float) (  (lHeight - 1) / 2);
    fSrcX2 = (float) (  (lWidth  - 1) / 2);
    fSrcY2 = (float) (  (lHeight - 1) / 2);
    fSrcX3 = (float) (- (lWidth  - 1) / 2);
    fSrcY3 = (float) (- (lHeight - 1) / 2);
    fSrcX4 = (float) (  (lWidth  - 1) / 2);
    fSrcY4 = (float) (- (lHeight - 1) / 2);

    // 计算新图四个角的坐标(以图像中心为坐标系原点)
    fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
    fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
    fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
    fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
    fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
    fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
    fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
    fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;


    // 计算旋转后的图像实际宽度
    lNewWidth  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);

    // 计算旋转后的图像高度
    lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);

    // 两个常数,这样不用以后每次都计算了
    f1  =  (float)  (-0.5  *  (lNewWidth  -  1)  *  fCosa  -  0.5  *  (lNewHeight  -  1)  *  fSina 
    +  0.5  *  (lWidth    -  1)); 
    f2  =  (float)  (  0.5  *  (lNewWidth  -  1)  *  fSina  -  0.5  *  (lNewHeight  -  1)  *  fCosa 
    +  0.5  *  (lHeight  -  1)); 


    //图像缩放
    //缩放比例
    float fXZoomRatio;
    float fYZoomRatio;

    fXZoomRatio=0.5f;
    fYZoomRatio=0.5f;

    // 缩放后图像的宽度和高度
    LONG lNewWidth2;
    LONG lNewHeight2;
    long    i1,j1;

    //// 计算缩放后的图像实际宽度
    lNewWidth2 = (LONG) (lNewWidth * fXZoomRatio + 0.5);
    //// 计算缩放后的图像高度
    lNewHeight2 = (LONG) (lNewHeight * fYZoomRatio + 0.5);

    unsigned char *lpNewBits2=new unsigned char[ lNewWidth2* lNewHeight2];

    for(int i = 0; i < lNewHeight2; i++)
    {
    // 针对图像每列进行操作
    for(int j = 0; j < lNewWidth2; j++)
    {
    // 计算该象素在源DIB中的坐标
    i0 = i / fYZoomRatio ;
    j0 = j / fXZoomRatio ;

    i1 = LONG(-((float) j0) * fSina + ((float) i0) * fCosa + f2+0.5);
    j1 =  LONG(((float) j0) * fCosa + ((float) i0) * fSina + f1+0.5);


    // 判断是否在源图范围内
    if( (j1 >= 0) && (j1 < lWidth) && (i1 >= 0) && (i1 < lHeight))
    {
    lpNewBits2[lNewWidth2*( lNewHeight2-1-i)+j]=lpDIBBits[lWidth*( lHeight-1-i1)+j1];

    }
    else
    {
    // 对于源图中没有的象素,直接赋值为255
    lpNewBits2[lNewWidth2*( lNewHeight2-1-i)+j] = 255;
    }
    }
    }


    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • ljooo
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 10:52:236楼 得分:0
    对不起,我说错了。因为程序没有界面了,我之前只是观察图像的像素的字符串,没看图像的显示效果。刚才我把代码复制一个有界面的程序,发现图像是可以识别的,只是发生了平移,水平垂直平移量刚好是宽度和高度的一半。 原因可能是图像旋转操作以中心的坐标的原点,而图像缩放以左上角为坐标的原点。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • rover___
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 17:05:457楼 得分:20
    旋转和缩放都可以用矩阵变换表示,把2个矩阵相乘(顺序可交换)再计算即可。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • kewei9
    • 等级:
    • 可用分等级:
    • 总技术分:
    • 总技术分排名:
    发表于:2008-08-08 17:33:058楼 得分:20
    可以合并
    旋转和缩放都对应图像的插值问题,主要是你把坐标变换搞清楚,插值实现还是比较简单
    修改 删除 举报 引用 回复

    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    世纪乐知(北京)网络技术有限公司 提供技术支持
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved