OpenCV —— 图像变换
将一副图像转变成另一种表现形式 ,比如,傅里叶变换将图像转换成频谱分量
卷积 —— 变换的基础
cvFilter2D 源图像 src 和目标图像 dst 大小应该相同
注意:卷积核的系数应该是浮点类型的,必须用 CV_32F 来初始化矩阵
cvFilter2D 函数内部处理边界 —— cvCopyMakeBorder (将特定的图像轻微变大,然后以一种方式填充图像边界)
梯度和Sobel导数
sobel 算子包含任意阶的微分以及融合偏导 大核对导数有更好的逼近,小核对噪声更加敏感
如果源图像src是8位的,为避免溢出,目标图像的深度必须是 IPL_DEPTH_16S
Scharr 滤波器
拉普拉斯变换 —— 二次导数 cvLaplace() —— 沿X轴Y轴的二次导数的和(周围是更高值的单点或者小块会使函数值最大化)
目标图像必须是16位(有符号)或者32位(浮点)图像
应用:检测团块,边缘检测 —— 原始图像的边缘位于拉普拉斯的值等于0的地方
Canny 算子 —— 首先在x和y方向求一阶导数,然后组合为4个方向的导数,这些方向导数达到局部最大值的点就是组成边缘的候选点;将独立的候选像素拼装成轮廓(应用滞后性阈值)
cvCanny —— 推荐的上下限阈值比例为2:1或3:1
霍夫变换 —— 二值图像中的任何点都可能是一些候选直线集合的一部分
OpenCV 支持两种不同形式的霍夫变换:标准霍夫变换(SHT),累计概率霍夫变换(PPHT)—— 减少计算时间
霍夫圆变换
- #include <cv.h>
- #include <highgui.h>
- #include <math.h>
- int main(int argc,char** argv)
- {
- IplImage* img=cvLoadImage("circle.jpg",CV_LOAD_IMAGE_GRAYSCALE);
- CvMemStorage* storage=cvCreateMemStorage();
- cvSmooth(img,img,CV_GAUSSIAN,,);
- CvSeq* results=cvHoughCircles(img,storage,CV_HOUGH_GRADIENT,,img->width/);
- for (int i=;i<results->total;i++)
- {
- float* p=(float*)cvGetSeqElem(results,i);
- CvPoint pt=cvPoint(cvRound(p[]),cvRound(p[]));
- cvCircle(img,pt,cvRound(p[]),CV_RGB(0xff,0xff,0x00));
- }
- cvNamedWindow("w1");
- cvShowImage("w1",img);
- cvWaitKey();
- cvReleaseMemStorage(&storage);
- cvDestroyAllWindows();
- return ;
- }
重映射
cvRemap() —— 用于矫正失真的标定或立体图像(涉及到插值问题)
仿射变换,透视变换
一个平面内的任意平行四边形ABCD可以被仿射为另一个平行四边形 ,仿射变换是透视变换的子集
稠密仿射变换 —— 图像扭曲必须进行一些插值运算以使输出的图像平滑 cvWarpAffine cvGetQuadrangleSubPix
仿射映射矩阵的计算 —— cvGetAffineTransform (两个包含三个点的数组,定义了两个平行四边形)
- // 首先利用 cvGetAffineTransform 计算变换矩阵,接下来做一次仿射变换
- #include <cv.h>
- #include <highgui.h>
- int main(int argc,char** argv)
- {
- CvPoint2D32f srcTri[],dstTri[];
- CvMat* rot_mat=cvCreateMat(,,CV_32FC1);
- CvMat* warp_mat=cvCreateMat(,,CV_32FC1);
- IplImage *src,*dst;
- src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_UNCHANGED);
- dst=cvCloneImage(src);
- dst->origin=src->origin;
- cvZero(dst);
- srcTri[].x=;
- srcTri[].y=;
- srcTri[].x=src->width-;
- srcTri[].y=;
- srcTri[].x=;
- srcTri[].y=src->height-;
- dstTri[].x=src->width*0.0;
- dstTri[].y=src->height*0.33;
- dstTri[].x=src->width*0.85;
- dstTri[].y=src->height*0.25;
- dstTri[].x=src->width*0.15;
- dstTri[].y=src->height*0.7;
- cvGetAffineTransform(srcTri,dstTri,warp_mat);
- cvWarpAffine(src,dst,warp_mat);
- cvCopy(dst,src);
- CvPoint2D32f center=cvPoint2D32f(src->width/,src->height/);
- double angle=-50.0;
- double scale=0.6;
- cv2DRotationMatrix(center,angle,scale,rot_mat);
- cvWarpAffine(src,dst,rot_mat);
- cvNamedWindow("w1");
- cvNamedWindow("w2");
- cvShowImage("w1",dst);
- cvShowImage("w2",src);
- cvWaitKey();
- cvReleaseImage(&dst);
- cvReleaseMat(&rot_mat);
- cvReleaseMat(&warp_mat);
- cvDestroyAllWindows();
- return ;
- }
稀疏仿射变换
cvTransform()
透视变换
密集透视变换 cvWarpPerspective()
计算透视映射矩阵 cvGetPerspectiveTransform
- // 透视变换
- /**/
- #include <cv.h>
- #include <highgui.h>
- int main(int argc,char** argv)
- {
- CvPoint2D32f srcQuad[],dstQuad[];
- CvMat *warp_matrix=cvCreateMat(,,CV_32FC1);
- IplImage *src,*dst;
- src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_GRAYSCALE);
- dst=cvCloneImage(src);
- dst->origin=src->origin;
- cvZero(dst);
- srcQuad[].x=;
- srcQuad[].y=;
- srcQuad[].x=src->width-;
- srcQuad[].y=;
- srcQuad[].x=;
- srcQuad[].y=src->height-;
- srcQuad[].x=src->width-;
- srcQuad[].y=src->height-;
- dstQuad[].x=src->width*0.05;
- dstQuad[].y=src->height*0.33;
- dstQuad[].x=src->width*0.9;
- dstQuad[].y=src->height*0.25;
- dstQuad[].x=src->width*0.2;
- dstQuad[].y=src->height*0.7;
- dstQuad[].x=src->width*0.8;
- dstQuad[].y=src->height*0.9;
- cvGetPerspectiveTransform(srcQuad,dstQuad,warp_matrix);
- cvWarpPerspective(src,dst,warp_matrix);
- cvNamedWindow("w1");
- cvShowImage("w1",dst);
- cvWaitKey();
- cvReleaseImage(&dst);
- cvReleaseMat(&warp_matrix);
- cvDestroyAllWindows();
- return ;
- }
稀疏透视变换 cvPerspectiveTransform
透视变换实际上是一个嵌入在三维空间的二维平面上的实际映射点映射回一个不同的二维子空间
cvCartToPolar cvPolarToCart
笛卡尔空间和极行或径向空间之间进行映射
对数极坐标变换 —— 人的视觉系统 —— 是对物体视场的一种不变表示 cvLogPolar
- #include <cv.h>
- #include <highgui.h>
- int main(int argc,char** argv)
- {
- IplImage* src;
- double M=; // 缩放比例
- src=cvLoadImage("wukong.jpg",CV_LOAD_IMAGE_GRAYSCALE);
- IplImage* dst=cvCreateImage(cvGetSize(src),,);
- IplImage* src2=cvCreateImage(cvGetSize(src),,);
- cvLogPolar(src,dst,cvPoint2D32f(src->width/,src->height/),M,CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS);
- cvLogPolar(dst,src2,cvPoint2D32f(src->width/,src->height/),M,CV_INTER_LINEAR|CV_WARP_INVERSE_MAP);
- cvNamedWindow("w1",);
- cvShowImage("w1",dst);
- cvNamedWindow("w2",);
- cvShowImage("w2",src2);
- cvWaitKey();
- cvReleaseImage(&dst);
- cvReleaseImage(&src2);
- cvDestroyAllWindows();
- return ;
- }
离散傅里叶变换 DFT
OpenCV 中实现了快速傅里叶变换,cvDFT 可以计算输入是一维或二维数组时的FFT
输入数组和输出数组必须是浮点类型并且通常是单通道或是双通道的
cvMulSpectrums 频谱乘法
- #include <cv.h>
- #include <highgui.h>
- void speedy_convolution(const CvMat* A,const CvMat* B,CvMat* C)
- {
- // 创建两个对于DFT算法维数最佳的新数组
- int dft_M=cvGetOptimalDFTSize(A->rows+B->rows-);
- int dft_N=cvGetOptimalDFTSize(A->cols+B->cols-);
- CvMat* dft_A = cvCreateMat(dft_M,dft_N,A->type);
- CvMat* dft_B=cvCreateMat(dft_M,dft_N,B->type);
- CvMat temp;
- cvGetSubRect(dft_A,&temp,cvRect(,,A->cols,A->rows));
- cvCopy(A,&temp);
- cvGetSubRect(dft_A,&temp,cvRect(A->cols,,dft_A->cols-A->cols,A->rows));
- cvZero(&temp);
- cvDFT(dft_A,dft_A,CV_DXT_FORWARD,A->rows);
- cvGetSubRect(dft_B,&temp,cvRect(,,B->cols,B->rows));
- cvCopy(B,&temp);
- cvGetSubRect(dft_B,&temp,cvRect(B->cols,,dft_B->cols-B->cols,B->rows));
- cvZero(&temp);
- cvDFT(dft_B,dft_B,CV_DXT_FORWARD,B->rows);
- // 所有频谱元素相乘
- cvMulSpectrums(dft_A,dft_B,dft_A,);
- cvDFT(dft_A,dft_A,CV_DXT_INV_SCALE,C->rows); // 反变换
- cvGetSubRect(dft_A,&temp,cvRect(,,C->cols,C->rows));
- cvCopy(&temp,C);
- cvReleaseMat(dft_A);
- cvReleaseMat(dft_B);
- }
离散余弦变换 DCT
类似于DFT,但所有系数都是实数 cvDCT
积分图像 —— 积分图像中的任意一点(x,y)的值是指从图像的左上角到这个点的所构成的矩形区域内所有点的灰度值之和
cvIntegral() —— 可以实现子区域的快速求和 —— 快速模糊,梯度估计,计算均值和标准差
距离变换 —— 定义一幅新图像,该图像中的每个输出像素被设成于输入像素0像素最近的距离 cvDistTransform()
输出图像必须是32位浮点类型图像
直方图均衡化
将直方图范围拉伸 ———— 映射函数应该是一个累计分布函数
cvEualizeHist(),原始图像以及目标图像必须是单通道,大小相同的8位图像。对于彩色图像,必须先将每个通道分开,再分别进行处理
OpenCV —— 图像变换的更多相关文章
- OPENCV图像变换-1
图像变换是指将一幅图像变换为图像数据的另一种表现形式,例如将图像进行傅立叶变换,或者对图像进行X,Y方向的求导等,经过这些变换,可以将图像数据处理中的某些问题换一个别的角度想办法,所以图像变换是图像处 ...
- OpenCV图像变换(仿射变换与透视变换)
仿射变换(affine transform)与透视变换(perspective transform)在图像还原.图像局部变化处理方面有重要意义.通常,在2D平面中,仿射变换的应用较多,而在3D平面中, ...
- OPENCV图像变换-2
一.经典霍夫变换 霍夫变换是图像处理中的一种特征提取技术,该方法通过在一个参数空间中通过计算累计结果的局部最大值来得到一个符合该特定形状的集合,作为结果. 运用两个坐标空间之间的变换,将一个空间中具有 ...
- python+opencv图像变换的两种方法cv2.warpAffine和cv2.warpPerspective
本文链接:https://blog.csdn.net/qq_27261889/article/details/80720359 # usr/bin/env python # coding: utf- ...
- OpenCV图像变换二 投影变换与极坐标变换实现圆形图像修正
投影变换 在放射变换中,物体是在二维空间中变换的.如果物体在三维空间中发生了旋转,那么这种变换就成为投影变换,在投影变换中就会出现阴影或者遮挡,我们可以运用二维投影对三维投影变换进行模块化,来处理阴影 ...
- <学习opencv>图像变换
拉伸.收缩.扭曲和旋转 统一调整大小 我们经常会遇到一些我们希望转换为其他尺寸的图像. 我们可能想要扩大或缩小图像; 这两项任务都是由同一个功能完成的. cv::resize() 该cv::resiz ...
- [opencv]<学习Opencv>英文原版翻译学习
[注]下文全部内容为 <<Learning OpenCV 3: Computer Vision in C++ with the OpenCV Library>>经由在线翻译整理 ...
- pyhton:图像旋转
最近一个作业中要用到图像旋转,分享一下学习过程.如有讲错的地方,恳请指正! 图像旋转,想想真简单啊,不就是将图像矩阵乘上一个旋转平移矩阵就完了吗?实际上还真没这么简单.首先这个旋转平移矩阵怎么获得?通 ...
- OpenCV-Python Tutorials目录
版本 3.4.6 1 Introduction to OpenCV OpenCV介绍Learn how to setup OpenCV-Python on your computer! 2 Gui F ...
随机推荐
- 由浅入深讲解数据库中Synonym的使用方法
1.Synonym的概念 Synonym(同义词)是SQL Server 2005的新特性.推出已经有几年的时间了.我们可以简单的理解Synonym为其他表的别名.本文中使用Northwind数据库为 ...
- 一篇文章助你理解Python3中字符串编码问题
前几天给大家介绍了unicode编码和utf-8编码的理论知识,以及Python2中字符串编码问题,没来得及上车的小伙伴们可以戳这篇文章:浅谈unicode编码和utf-8编码的关系和一篇文章助你理解 ...
- mybatis-generator-core快速生成实体类和Mapper
日常使用Mybatis少不了和实体类和 Mapper 打交道.除了我们手写来实现,还可以使用 mybatis-generator-core 来快速生成 实体类和 Mapper. 步骤如下: 1.下载 ...
- MySql系列之多表查询
多表连接查询 #重点:外链接语法 SELECT 字段列表 FROM 表1 INNER|LEFT|RIGHT JOIN 表2 ON 表1.字段 = 表2.字段; 交叉连接:不适用任何匹配条件.生成笛卡尔 ...
- 对比学习sass和stylus的常用功能
在众多的css预处理器语言中,sass和stylus算是十分优秀的两个.本文主要针对两者的常用功能做个简单的对比分析.在对比中了解二者的差异,同时帮助大家更好的掌握这两种预处理语言.本文涉及到的sas ...
- vue-router 实现无效路由(404)的友好提示
最近在做一个基于vue-router的SPA,想对无效路由(404)页面做下统一处理.这次我真的没有在官方文档找到具体的说明[捂脸]所以本文仅是我DIY的一个思路,求轻虐=_= 在我的理解中,vue- ...
- NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统
原文:NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统 前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的 ...
- poj 2533 Longest Ordered Subsequence 最长递增子序列(LIS)
两种算法 1. O(n^2) #include<iostream> #include<cstdio> #include<cstring> using namesp ...
- Zookeeper简单概念介绍
过去,每个应用都是一个CPU.一个主机上的单一系统.然而今天,随着大数据和云计算时代的到来,不论什么相互独立的程序都可以运行在多个计算机上.然而面临的问题是,协调这些集群的系统比在单一主机上要复杂的多 ...
- Java编程手冊-Collection框架(下)
建议先看Java编程手冊-Collection框架(上) 5. Set<E>接口与实现 Set<E>接口表示一个数学的集合,它不同意元素的反复,仅仅能包括一个null元素. ...