第六章 学习OpenCV——图像变换

第六章 学习OpenCV——图像变换

目录

例6-1 使用霍夫变换寻找直线、圆和其他简单形状

本例完成的工作如下:

 1.  使用cvHoughCircles返回灰度图中找到的圆序列(例6-1);
 2.  载入一个包括清晰直线和圆的图像,比如一辆侧面看的自行车,调用霍夫直线变换和霍夫圆变换处理这幅图像(第六章 练习8);
 3.  利用霍夫变换识别不同周长的任意形状(第六章 练习9);

具体代码如下:

#include <cv.h>
#include <highgui.h>  
#include <math.h>

using namespace std;

int main(int argc, char* argv[])
{
    IplImage *Image,*Ihough;                        //图像
    IplImage *Input1, *Ihough_line, *Ihough_circle; //图像
    IplImage *Input2, *IHough;                      //图像

    if ((Image = cvLoadImage("D:\\Template\\OpenCV\\Template37_Hough_Circle_Line\\Debug\\2.jpg", CV_LOAD_IMAGE_GRAYSCALE)) == 0)
        return -1;
    if ((Input1 = cvLoadImage("D:\\Template\\OpenCV\\Template37_Hough_Circle_Line\\Debug\\1.jpg", CV_LOAD_IMAGE_GRAYSCALE)) == 0)
        return -2;
    if ((Input2 = cvLoadImage("D:\\Template\\OpenCV\\Template37_Hough_Circle_Line\\Debug\\7.jpg", CV_LOAD_IMAGE_GRAYSCALE)) == 0)
        return -3;

    Ihough=cvCreateImage(cvGetSize(Image), Image->depth, Image->nChannels);
    Ihough_line = cvCreateImage(cvGetSize(Input1), Image->depth, Image->nChannels);
    Ihough_circle = cvCreateImage(cvGetSize(Input1), Image->depth, Image->nChannels);
    IHough = cvCreateImage(cvGetSize(Input2), Image->depth, Image->nChannels);

    CvMemStorage *storage0 = cvCreateMemStorage(0);     //分配存储区域
    CvMemStorage *storage1 = cvCreateMemStorage(0);     //分配存储区域
    CvMemStorage *storage2 = cvCreateMemStorage(0);     //分配存储区域
    CvMemStorage *storage3 = cvCreateMemStorage(0);     //分配存储区域
    CvMemStorage *storage4 = cvCreateMemStorage(0);     //分配存储区域

    //cvSmooth(Image, Image, CV_GAUSSIAN, 3, 3);        //高斯平滑
    cvCanny(Image, Ihough, 50, 150);                    //边缘检测
    cvCanny(Input1, Ihough_line, 50, 150);              //边缘检测
    cvCanny(Input1, Ihough_circle, 50, 150);            //边缘检测
    cvCanny(Input2, IHough, 50, 150);                   //边缘检测

    CvSeq *results = cvHoughCircles(Ihough, storage0, CV_HOUGH_GRADIENT, 2, Ihough->width / 10, 50, 200, 0, 0);
    //CvSeq *results = cvHoughCircles(Image, storage, CV_HOUGH_GRADIENT, 2, Image->width / 10);
    //输入 存储区域 霍夫变换方式 累加器分辨率 两圆间隔最小值 边缘阈值 累加器阈值(认定为圆)半径最小值 最大值

    for (int i = 0; i <= results->total; i++)                   //序列元素个数
    {
        float *p = (float*)cvGetSeqElem(results, i);            //提取序列元素
        CvPoint pt1 = cvPoint(cvRound(p[0]),cvRound(p[1]));     //四舍五入取整
        cvCircle(Ihough, pt1, cvRound(p[2]), CV_RGB(100, 100, 100), 8); //画圆
    }

    CvSeq *result1 = cvHoughLines2(Ihough_line, storage1, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 50, 100, 10);
    //输入 存储区域 霍夫变换方式 累加器分辨率(像素) 累加器分辨率(弧度) 累加器阈值(认定为直线)
    //直线最小长度 分离线段分隔点数

    //对于SHT和MSHT方法来说,返回的是Rho值和theta值,如下还原
    //for (int i = 0; i < MIN(line->total, 100); i++)
    //{
   
    //  float* lines = (float*)cvGetSeqElem(line, i);
    //  float rho = lines[0];
    //  float theta = lines[1];
    //  CvPoint pt1, pt2;
    //  double a = cos(theta), b = sin(theta);
    //  double x0 = a*rho, y0 = b*rho;
    //  pt1.x = cvRound(x0 + 1000 * (-b));
    //  pt1.y = cvRound(y0 + 1000 * (a));
    //  pt2.x = cvRound(x0 - 1000 * (-b));
    //  pt2.y = cvRound(y0 - 1000 * (a));
    //  cvLine(result, pt1, pt2, CV_RGB(255, 0, 0));
    //}

    //对于PPHT方法,返回的就是直线端点的坐标
    for (int i = 0; i <= result1->total; i++)                           //序列元素个数
    {
        CvPoint* line = (CvPoint*)cvGetSeqElem(result1, i);
        cvLine(Ihough_line, line[0], line[1], CV_RGB(100,100,100), 4);  //画线  
        cout << "2 : " << line[0].x << " " << line[0].y << endl;
        cout << line[1].x << " " << line[1].y << endl << endl;
    }

    CvSeq *result2 = cvHoughCircles(Ihough_line, storage2, CV_HOUGH_GRADIENT, 2, Ihough->width / 10, 50, 200, 50, 100);
    //输入 存储区域 霍夫变换方式 累加器分辨率 两圆间隔最小值 边缘阈值 累加器阈值(认定为圆)半径最小值 最大值
    for (int i = 0; i <= result2->total; i++)                           //序列元素个数
    {
        float *circle = (float*)cvGetSeqElem(result2, i);               //提取序列元素
        CvPoint pt2 = cvPoint(cvRound(circle[0]), cvRound(circle[1]));  //四舍五入取整
        cvCircle(Ihough_circle, pt2, cvRound(circle[2]), CV_RGB(100, 100, 100), 8); //画圆
    }

    CvSeq *result3 = cvHoughLines2(IHough, storage3, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180,1);
    //输入 存储区域 霍夫变换方式 累加器分辨率(像素) 累加器分辨率(弧度) 累加器阈值(认定为直线)
    //(直线最小长度 分离线段分隔点数)

    //对于PPHT方法,返回的就是直线端点的坐标
    for (int i = 0; i <= result3->total; i++)                           //序列元素个数
    {

        CvPoint* Line = (CvPoint*)cvGetSeqElem(result3, i);
        cvLine(IHough, Line[0], Line[1], CV_RGB(100, 100, 100), 4);     //画线 
    }

    cvNamedWindow("Image", 1);
    cvNamedWindow("cvHoughCircles", 1);
    cvNamedWindow("Input1", 1);
    cvNamedWindow("Ihough_line", 1);
    cvNamedWindow("Ihough_circle", 1);
    cvNamedWindow("Input2", 1);
    cvNamedWindow("IHough", 1);

    cvShowImage("Image", Image);
    cvShowImage("cvHoughCircles", Ihough);
    cvShowImage("Input1", Input1);
    cvShowImage("Ihough_line", Ihough_line);
    cvShowImage("Ihough_circle", Ihough_circle);
    cvShowImage("Input2", Input2);
    cvShowImage("IHough", IHough);

    cvWaitKey(0);

    cvReleaseImage(&Image);
    cvReleaseImage(&Ihough);
    cvReleaseImage(&Input1);
    cvReleaseImage(&Ihough_line);
    cvReleaseImage(&Ihough_circle);
    cvReleaseImage(&Input2);
    cvReleaseImage(&IHough);

    cvDestroyWindow("Image");
    cvDestroyWindow("cvHoughCircles");
    cvDestroyWindow("Input1");
    cvDestroyWindow("Ihough_line"); 
    cvDestroyWindow("Ihough_circle");
    cvDestroyWindow("Input2");
    cvDestroyWindow("IHough");
    return 0;
}

运行结果如下图:
霍夫变换

例6-2 使用仿射、透视变换、对数极变换

本例完成的工作如下:

 1.  使用cvWarpAffine实现仿射变换(例6-2);
 2.  使用cvWarpPerspective实现透视变换(例6-3);
 3.  使用cvLogPolar实现对数极变换(例6-4);
 4.  载入一幅图像,进行透视变换,然后旋转,在一步之内完成,与本例2在同一图像中实现(第六章 练习17);

具体代码如下:

#include <cv.h>
#include <highgui.h>  
#include <stdlib.h>  
#include <stdio.h> 
#include <math.h>

using namespace std;

int main(int argc, char* argv[])
{
    IplImage* src, *Iaffine, *Irot, *Iperspective;  //变换图像与原图像
    IplImage*Ipolar, *Ipolar_inverse;               //极坐标变换图像

    CvPoint2D32f srcTri[3], dstTri[3];              //仿射变换的两个点集
    CvPoint2D32f srcQuad[4], dstQuad[4];            //透视变换的两个点集

    CvMat* rot_matrix = cvCreateMat(2, 3, CV_32FC1);            //仿射变换矩阵(旋转)
    CvMat* affine_matrix = cvCreateMat(2, 3, CV_32FC1);         //仿射变换矩阵
    CvMat* perspective_matrix = cvCreateMat(3, 3, CV_32FC1);    //透视变换矩阵

    if (!(src = cvLoadImage("D:\\Template\\OpenCV\\Template38_Affine_Perspective_Polar\\Debug\\3.jpg")))
        return -1;

    Iaffine = cvCloneImage(src);            //克隆图像
    Iaffine->origin = src->origin;          //设置相同原点
    cvZero(Iaffine);                        //清零
    Irot = cvCloneImage(src);               //克隆图像
    Irot->origin = src->origin;             //设置相同原点
    cvZero(Irot);                           //清零
    Iperspective = cvCloneImage(src);       //克隆图像
    Iperspective->origin = src->origin;     //设置相同原点
    cvZero(Iperspective);                   //清零

    Ipolar = cvCloneImage(src);             //克隆图像
    Ipolar->origin = src->origin;           //设置相同原点
    cvZero(Ipolar);                         //清零
    Ipolar_inverse = cvCloneImage(src);     //克隆图像
    Ipolar_inverse->origin = src->origin;   //设置相同原点
    cvZero(Ipolar_inverse);                 //清零

    //旋转参数
    double angle = -35.0;
    double scale = 0.75;
    CvPoint2D32f center = cvPoint2D32f(src->width / 2, src->height / 2);

    //极坐标变换参数
    double M =25;                       //缩放比例

    //仿射变换点
    srcTri[0].x = 0;                    //左上
    srcTri[0].y = 0;
    srcTri[1].x = src->width - 1;       //右上
    srcTri[1].y = 0;
    srcTri[2].x = 0;                    //左下
    srcTri[2].y = src->height - 1;

    dstTri[0].x = src->width*0.05;      //左上
    dstTri[0].y = src->height*0.33;
    dstTri[1].x = src->width*0.9;       //右上
    dstTri[1].y = src->height*0.25;
    dstTri[2].x = src->width*0.2;       //左下
    dstTri[2].y = src->height*0.7;

    //透视变换点
    srcQuad[0].x = 0;                   //左上
    srcQuad[0].y = 0;
    srcQuad[1].x = src->width - 1;      //右上
    srcQuad[1].y = 0;
    srcQuad[2].x = 0;                   //左下
    srcQuad[2].y = src->height - 1;
    srcQuad[3].x = src->width - 1;      //右下
    srcQuad[3].y = src->height - 1;

    dstQuad[0].x = src->width*0.9;      //左上
    dstQuad[0].y = src->height*0.25;
    dstQuad[1].x = src->width*0.8;      //右上
    dstQuad[1].y = src->height*0.9;
    dstQuad[2].x = src->width*0.05;     //左下
    dstQuad[2].y = src->height*0.33;
    dstQuad[3].x = src->width*0.2;      //右下
    dstQuad[3].y = src->height*0.7;


    //dstQuad[0].x = src->width*0.05;       //左上
    //dstQuad[0].y = src->height*0.33;
    //dstQuad[1].x = src->width*0.9;        //右上
    //dstQuad[1].y = src->height*0.25;
    //dstQuad[2].x = src->width*0.2;        //左下
    //dstQuad[2].y = src->height*0.7;
    //dstQuad[3].x = src->width*0.8;        //右下
    //dstQuad[3].y = src->height*0.9;

    cvGetAffineTransform(srcTri, dstTri, affine_matrix);        //仿射变换矩阵        
    cv2DRotationMatrix(center,angle,scale,rot_matrix);          //仿射(旋转)变换矩阵    
    cvGetPerspectiveTransform(srcQuad, dstQuad, per
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值