《学习OpenCV》练习题第四章第七题abc

《学习opencv》笔记——矩阵和图像操作——cvGEMM,cvGetCol,cvGetCols and cvGetDiag 阅读详情

题外话:一直是打算把这本书的全部课后编程题写完的,中间断了几个月,一直忙于其他事。现在开始补上。

这道题我不清楚我理解的题意是不是正确的,这道题可以练习用OpenCV实现透视变换(可以用于矫正在3维环境下的图像失真),b&c部分则是实现图像放大缩小插值,旋转图像。所有的功能都和键盘事件处理联系起来,纯OpenCV实现,和OS无关。不过,在处理SHIFT键时,我取得是其在键盘上对应字符的ASCII码,好像OpenCV对键盘事件的支持不如对鼠标事件的支持。所以SHIFT键+小键盘上的数字键是不行的。

代码:

#include <opencv/highgui.h>
#include <opencv/cv.h>
#include <opencv_libs.h>

/*
 *《学习OpenCV》第四章第七题  
 * 完成时间:0:23 10/4 星期五 2013  
 */    

#define   WARPSTEPSIZE     0.01      // 透视变换矩阵每次的变化率

#define   RESIZESTEPSIZE   0.1       // 放大、缩小每次的变化率

#define   ROTATESTEPSIZE   10        // 旋转图像时每次旋转的角度(逆时针)

// 透视变换目标变换矩阵
CvPoint2D32f g_dstQuad[4];

// image width & height
int g_width = 0;
int g_height = 0;

// rotate degree
int g_RotateDegree = 0;  

/*
 * function: Zoom in or zoom out an image.
 * param: inorout -- indicate in or out(0 means zoom in; 1 means zoom out)
 * param: the destination size.
 */
CvSize getZoomDstSize(int inorout)
{
    if(inorout != 0 && inorout != 1)
    {
        return cvSize(-1, -1);
    }
    if(g_height == 0 || g_width == 0)
    {
        return cvSize(-1, -1);
    }

    // Zoom in
    if(inorout == 0)
    {
        g_width += g_width * RESIZESTEPSIZE;
        g_height += g_height * RESIZESTEPSIZE;
    }
    else if(inorout == 1)
    {
        g_width -= g_width * RESIZESTEPSIZE;
        g_height -= g_height * RESIZESTEPSIZE;

        if(g_height < 1)
        {
            g_height = 1;
        }
        else if(g_width < 1)
        {
            g_width = 1;
        }
    }

    return cvSize(g_width, g_height);
}

void rotateImage(IplImage* img, IplImage *img_rotate,float degree)  
{  
    // 旋转中心
    CvPoint2D32f center;    
    center.x=float (img->width/2.0+0.5);  
    center.y=float (img->height/2.0+0.5);  
    // 计算二维旋转的仿射变换矩阵  
    float m[6];              
    CvMat M = cvMat( 2, 3, CV_32F, m );  
    cv2DRotationMatrix( center, degree,1, &M);  
    // 变换图像,并用黑色填充其余值  
    cvWarpAffine(img,img_rotate, &M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,cvScalarAll(0) );  
} 

/*
 * function: change the g_dstQuad(minus or plus one of the element)
 * param: index -- which element(0 -- 4)
 * param: xory -- indicate x or y to change(0 means x; 1 means y)
 * param: operation -- indicate which operation(0 means plus; 1 means minus) 
 * return: 0 means success.  -1 means failed.
 */
int changeg_dstQuad(int index, int xory, int operation)
{
    // param check
    if( index > 3 || index < 0 || 
        (xory != 0 && xory != 1) ||
        (operation != 0 && operation != 1) ||
        g_width == 0 || g_height == 0)
    {
        return -1;
    }

    // plus
    if(operation == 0)
    {
        if(xory == 0)    // x
        {
            g_dstQuad[index].x += WARPSTEPSIZE * g_width;
            if(g_dstQuad[index].x > g_width - 1)
            {
                g_dstQuad[index].x = g_width - 1;
            }
        }
        else if(xory == 1)   // y
        {
            g_dstQuad[index].y += WARPSTEPSIZE * g_height;
            if(g_dstQuad[index].y > g_height - 1)
            {
                g_dstQuad[index].y = g_height -1;
            }
        }
    }
    
    // minus
    else if (operation == 1)
    {
        if(xory == 0)        // x
        {
            g_dstQuad[index].x -= WARPSTEPSIZE * g_width;
            if(g_dstQuad[index].x < 0)
            {
                g_dstQuad[index].x = 0;
            }
        }
        else if(xory == 1 )   // y
        {
            g_dstQuad[index].y -= WARPSTEPSIZE * g_height;
            if(g_dstQuad[index].y < 0)
            {
                g_dstQuad[index].y = 0;
            }
        }
    }

    return 0;
}

int main()
{
    const char * FILEPATH = "lena.bmp";
    IplImage * src = cvLoadImage(FILEPATH, CV_LOAD_IMAGE_UNCHANGED);

    if(!src)
    {
        printf("load image error.\texit\n");
        return -1;
    }

    CvPoint2D32f srcQuad[4];
    CvMat* warp_matrix = cvCreateMat(3, 3, CV_32FC1);
    IplImage *dst;

    cvNamedWindow("Source_Image", 1);
    cvNamedWindow("Perspective_Warp", 1);

    dst = cvCloneImage(src);
    dst->origin = dst->origin;
    cvZero(dst);

    // image width & height
    g_width = src->width;
    g_height = src->height;

    srcQuad[0].x = 0;               // src Top left
    srcQuad[0].y = 0;
    srcQuad[1].x = g_width - 1;   // src Top right
    srcQuad[1].y = 0;
    srcQuad[2].x = 0;                // src Bottom left
    srcQuad[2].y = g_height - 1;  
    srcQuad[3].x = g_width - 1;     // src Bottom right
    srcQuad[3].y = g_height - 1;

    g_dstQuad[0].x = 0;           // dst Top left
    g_dstQuad[0].y = 0;
    g_dstQuad[1].x = g_width - 1;   // dst Top right
    g_dstQuad[1].y = 0;
    g_dstQuad[2].x = 0;           // dst Bottom left
    g_dstQuad[2].y = g_height - 1;
    g_dstQuad[3].x = g_width - 1;   // dst Bottom right
    g_dstQuad[3].y = g_height - 1;

    while(1)
    {
        cvShowImage("Source_Image", src);
        char c = cvWaitKey(10);
       
        int ret = 0;
        switch(c)
        {
        // ESC
        case 27:
            goto end;
            break;
        // 0 -- 放大图像
        case 48:
            {
                cvNamedWindow("Resize", 1);
                CvSize dstSize = getZoomDstSize(0);
                if(dstSize.height == -1 || dstSize.width == -1)
                {
                    goto end;
                }

                IplImage* imageresize = cvCreateImage(dstSize, src->depth, src->nChannels);
                if(!imageresize)
                {
                    goto end;
                }
                cvResize(src, imageresize, CV_INTER_LINEAR);
                cvShowImage("Resize", imageresize);
                cvReleaseImage(&imageresize);
            }
            break;
        // SHIFT + 0 ')' -- 缩小图像
        case 41:
            {
                cvNamedWindow("Resize", 1);
                CvSize dstSize = getZoomDstSize(1);
                if(dstSize.height == -1 || dstSize.width == -1)
                {
                    goto end;
                }

                IplImage* imageresize = cvCreateImage(dstSize, src->depth, src->nChannels);
                if(!imageresize)
                {
                    goto end;
                }
                cvResize(src, imageresize, CV_INTER_LINEAR);
                cvShowImage("Resize", imageresize);
                cvReleaseImage(&imageresize);
            }
            break;
        // 9 -- 旋转图像(逆时针)
        case 57:
            {
                cvNamedWindow("Rotate", 1);
                
                IplImage* imagerotate = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
                if(!imagerotate)
                {
                    goto end;
                }
                g_RotateDegree += ROTATESTEPSIZE;
                rotateImage(src, imagerotate, g_RotateDegree);
                cvShowImage("Rotate", imagerotate);
                cvReleaseImage(&imagerotate);
            }
            break;
        // SHIFT + 9 '(' -- 旋转图像(顺时针)
        case 40:
            {
                cvNamedWindow("Rotate", 1);

                IplImage* imagerotate = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
                if(!imagerotate)
                {
                    goto end;
                }
                g_RotateDegree -= ROTATESTEPSIZE;
                rotateImage(src, imagerotate, g_RotateDegree);
                cvShowImage("Rotate", imagerotate);
                cvReleaseImage(&imagerotate);
            }
            break;
        // 1
        case 49:
            ret = changeg_dstQuad(0, 0, 0);
            break;
        // 2
        case 50:
            ret = changeg_dstQuad(0, 1, 0);
            break;
        // 3
        case 51:
            ret = changeg_dstQuad(1, 0, 0);
            break;
        // 4
        case 52:
            ret = changeg_dstQuad(1, 1, 0);
            break;
        // 5
        case 53:
            ret = changeg_dstQuad(2, 0, 0);
            break;
        // 6
        case 54:
            ret = changeg_dstQuad(2, 1, 0);
            break;
        // 7
        case 55:
            ret = changeg_dstQuad(3, 0, 0);
            break;
        // 8
        case 56:
            ret = changeg_dstQuad(3, 1, 0);
            break;
        // SHIFT + 1  '!'
        case 33:
            ret = changeg_dstQuad(0, 0, 1);
            break;
        // SHIFT + 2  '@'
        case 64:
            ret = changeg_dstQuad(0, 1, 1);
            break;
        // SHIFT + 3 '#'
        case 35:
            ret = changeg_dstQuad(1, 0, 1);
            break;
        // SHIFT + 4 '$'
        case 36:
            ret = changeg_dstQuad(1, 1, 1);
            break;
        // SHIFT + 5 '%'
        case 37:
            ret = changeg_dstQuad(2, 0, 1);
            break;
        // SHIFT + 6 '^'
        case 94:
            ret = changeg_dstQuad(2, 1, 1);
            break;
        // SHIFT + 7 '&'
        case 38:
            ret = changeg_dstQuad(3, 0, 1);
            break;
        // SHIFT + 8 '*'
        case 42:
            ret = changeg_dstQuad(3, 1, 1);
            break;

        default:
            break;
        }

        // Error
        if(ret != 0)
        {
            goto end;
        }
        cvGetPerspectiveTransform(srcQuad, g_dstQuad, warp_matrix);
        cvWarpPerspective( src, dst, warp_matrix, 
                           CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));

        cvShowImage("Source_Image", src);
        cvShowImage("Perspective_Warp", dst);
    }

end:
    cvReleaseImage(&src);
    cvReleaseImage(&dst);
    cvReleaseMat(&warp_matrix);
    cvDestroyAllWindows();

    return 0;
}

程序运行截图:

首先是透视变换:


图像放大缩小(b部分):


图像旋转(c部分):


OpenCV中contourArea轮廓面积算法 本博文有关opencv中轮廓面积contourarea算法 阅读详情

相关推荐

Opencv学习笔记 透视变换/单应性变换

拉伸、收缩、扭曲、旋转是图像的几何变换,在三维视觉技术中大量应用到这些变换,又分为仿射变换和透视变换。仿射变换通常用单应性建模,利用cvWarpAffine解决密集映射,用cvTransform解决稀疏映射。仿射变换可以将矩形转换成平行四边形,它可以将矩形的边压扁但必须保持边是平行的,也可以将矩形旋转或者按比例变化。透视变换提供了更大的灵活性,一个透视变换可以将矩阵转变成梯形。当然,平行四边形也是梯形,所以仿射变换是透视变换的子集。

学以致用 知行合一 4593

opencv期末练习题(4)附带解析

这段代码创建了一个黑色画板,支持在画板上通过滑动鼠标画出圆形线条。用户可以按下 'q' 键退出程序,按下 'm' 键切换画图模式,此时在滑动鼠标会在画板上画出圆形线条。这个简单的画板演示了如何使用 OpenCV 处理鼠标事件,根据用户的输入在画板上绘制图形。如果用户按下 'q' 键,则退出程序;如果按下 'm' 键,则切换画图模式。,在函数中根据当前是否处于画图模式以及鼠标事件类型,在画板上画出圆形线条。进入死循环,不断显示当前画板,并等待用户的键盘输入。用于保存左键按下和释放时的坐标,

weixin_45266691的博客 568

【Labview与SQL Server互联(labview可以引用数据库)】

Labview与SQL Server互联

Magize的博客 3585

OpenCV练习(2)图像校正

创建一个目标点数组。

PLANTTHESON的博客 2341

winpcap无法安装提示新版本已经安装解决办法

问题显示如下该问题会导致ensp里的云识别不到网卡可能是因为之前安装了npcap,而且安装时勾选了第四个选项导致无法安装,需要完全卸载npcap解决办法:办法一:在控制面板的程序与卸载里面卸载npcap和winPcap,然后再安装winPcap,如果搜不到往下看办法二:在C:\Windows\SysWOW64目录下搜索wpcap.dll和packet.dll并重命名为wpcap.dll.old和packet.dll.old办法三:如果搜不到这两个文件需要安装win10Pcap才能找到这两个文件下载地址:Wi

qq_73202377的博客 3万+

后台扫描工具 - 御剑(珍藏版)附下载

版本说明:御剑后台扫描珍藏版 下载地址:安装包放下方网盘里了 链接:https://pan.baidu.com/s/1Bn7GtWb7AStcjzVahFOjSQ 提取码:zkaq 使用环境:windows 标题工具说明: 御剑后台扫描珍藏版是T00LS大牛的作品,方便查找用户后台登陆地址,同时也为程序开发人员增加了难度,尽量独特的后台目录结构。 附带很强大的字典,字典我们也是可以自己修改的,继续增加规则。 一、御剑后台扫描工具简介: 1、扫描线程自定义:用户可根据自身电脑的配置来设置调节扫描线程 2、

hackzkaq的博客 4万+

opencv基本练习

opencv的基本使用

qq_43594227的博客 209

激光定位算法竞技场:hdl_localization与Cartographer/AMCL的横向技术解剖

本文深入对比了hdl_localization、Cartographer和AMCL三种激光定位算法的技术原理与性能表现。通过UKF-NDT融合、图优化和粒子滤波等核心技术,分析了各算法在结构化环境、动态环境和大尺度场景下的适应性。实验数据表明,Cartographer在全局一致性上表现最优,而AMCL在动态环境中更具鲁棒性。文章还提供了算法选型指南和参数调优技巧,为工程实践提供参考。

weixin_29062865的博客 365

OpenCV的简单练习

【代码】OpenCV的简单练习。

qq_63603839的博客 1011

fragstats:景观指数趋势分析

优快云@_养乐多_本文将介绍景观指数时间序列的趋势分析,包括趋势类型、斜率、截距等。以及景观指数突变分析所用的软件和 python 代码。结果如下图所示,

养乐多的博客 2859

Windows 11 安装 JDK 25:下载、安装、配置环境变量、验证

本文详细介绍了在 Windows 11 系统上安装 JDK 25 的完整流程,包括从 Oracle 官网下载压缩包、解压至自定义目录、配置 JAVA_HOME 与 Path 环境变量,并验证安装是否成功。文章推荐使用 ZIP 压缩包而非 EXE 安装程序,以实现绿色便携、多版本共存和灵活管理。最后通过一个使用 Java 25 新特性的示例程序,验证 JDK 的编译与运行环境。

寒水馨 · 轻量级技术文档 · hanshuixin.org 7661

《学习OpenCV》练习题第三章第八题a

#include #include #include #pragma comment (lib,"opencv_calib3d231d.lib") #pragma comment (lib,"opencv_contrib231d.lib") #pragma comment (lib,"opencv_core231d.lib") #pragma comment (lib,"opencv_fe

qdsclove的专栏 1371

Darknet-Yolov3 移植过程

本教程面向使用寒武纪平台进行深度学习推理任务的开发者。针对当前主流检测网络darknet-yolov3,进行寒武纪平台的移植。开发者对照移植过程,能够利用寒武纪智能处理器设备完成多种场景的目标检测任务。本实验代码基于 Neuware 1.6.1 与 Python 2.7 环境。

shengyin714959的博客 438

《学习OpenCV》练习题第五章第二题abc

代码: #include #include #include #include /* *《学习OpenCV》第五章第二题 * 完成时间:21:43 10/13 星期日 2013 * 作者:qdsclove@163.com */ /* Image Size */ #define IMG_SIZE 100 /* * Window Title */ #

qdsclove的专栏 1771

手把手教你学GPU的KMD专栏--3.4 中断处理机制与优化

记住,中断处理是GPU与CPU通信的"桥梁",没有高效的中断处理,GPU的性能将无法充分发挥。KMD通过"快进快出"原则、事件标志机制、GPU本机围栏等技术,实现高效、低延迟的中断处理。:GPU本机围栏机制允许GPU在满足特定条件(如围栏值达到某个阈值)时才触发中断,而不是每次围栏更新都触发中断,从而显著减少CPU唤醒次数,降低功耗。正如Microsoft GPU架构师在2022年WinHEC大会上指出:"没有好的中断处理,再强大的GPU也会被系统延迟拖垮。:多个GPU设备共享中断,导致中断处理混乱。

MHD0815的博客 112

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

2023亚太杯数学建模ABC题思路代码模型分析

2023亚太杯数学建模ABC题思路分析

UST数模社的博客 1326

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

opencv中 overwrite 的使用情况ABC

在OPENCV中只支持avi格式的视频流,而且大小不能超过2GB。并且不能添加音频。

junjie58msp的专栏 874

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Opencv(C++)学习之 一种用opencv实现高斯曲线拟合的方法

1、用opencv实现高斯曲线拟合

lez1021的博客 4374

第八周学习报告(opencv学习)

见第一次接触opencv,所以是从头开始学的。

m0_74071912的博客 208

卸载opencv 安装cuda版本的opencv

一、卸载opencv (如果没装那直接跳过这一步) 1、查看已安装的 opencv 版本 pkg-config --modversion opencv//或pkg-config --modversion opencv4 2、卸载 sudo make uninstall cd .. sudo rm -rf build 2.清理 /usr 中所有 opencv 相关项 //注意这里为了确保删干净重复写了一些路径,建议大家打开文件夹对照代码所示路径一个个删除 sudo rm -r /usr/local/in

z1872385的博客 1万+

OpenCV-透视变换及对二维点求透视变换之后的坐标

OpenCV-透视变换及对二维点求透视变换之后的坐标 微信公众号:幼儿园的学霸 个人的学习笔记,关于OpenCV,关于机器学习, …。问题或建议,请公众号留言; 目录 前言 基本原理 OpenCV透视变换函数代码 前言   在做车道线检测中用到了透视变换的一点内容,用于将相机拍摄的图像转换到道路平行的视角下,即鸟瞰图,然后在鸟瞰图中进行车道线检测。   如图1、图2所示分别为相机...

leonardohaig的博客 1万+

【OpenCV图像处理2】OpenCV 基础知识

OpenCV图像处理第二部分:OpenCV 基础知识。主要内容包含:OpenCV的色彩空间、Numpy的基本操作、OpenCV的重要数据结构-Mat。

leoatliang的博客 1867

学习Opencv笔记

Opencv学习笔记

流星 376

openCV【实践系列】5——使用OpenCV进行Delaunay三角剖分

使用OpenCV进行Delaunay三角剖分和Voronoi图 图1:左图奥巴马总统使用dlib检测到标志点,中间Delaunay三角剖分的标志点,右图:相应的Voronoi图 在面部标志的众多应用中,首先发现面部地标的三角测量(参见图1),并且这些三角形被扭曲来一些有趣的事情。这篇文章将帮助我们理解Delaunay三角剖分和Voronoi图(又名Voronoi tesselation,Voronoi分解,Voronoi分区和Dirichlet曲面细分),并帮助我们发现Open...

aitail的博客 3330

OpenCV模块分类

OpenCV模块包括: core——定义了基本数据结构,核心功能,尤其是底层数据结构和算法函数,例如最重要的Mat和一些其他的模块 imgproc——该模块包括了线性和非线性的图像滤波,图像的几何变换,颜色空间转换,直方图处理等图像处理函数 video——该模块包括运动估计,背景分离、前景提取,特征跟踪函数与类 calib3d——基本的双目几何算法,单摄像头标定,物体...

228

毕业设计教程:Linux上Opencv与Qt实现的人脸识别的考勤点名/门禁系统(PC/嵌入式ARM/树莓派)

前言: 原毕业设计作品:https://blog.youkuaiyun.com/qq_30155503/article/details/102764838,是一个人脸识别的门禁系统开源源码及论文,基本功能实现,但其教程较简略且有欠缺。 本教程将从零开始,手把手教你如何一步一步实现人脸识别,意在打造一个升级完整版、全优快云最详细版。本篇将有两个版本:PC端Ubuntu与嵌入式ARM版本。 本教程将从基本..............................

曾哥哥的博客 1万+
上一篇: 基于HSI颜色模型实现去除照片的“红眼现象”
下一篇: 《学习OpenCV》练习题第四章第八题ab
Stk_OverFlow
博客等级 码龄14年 27粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值