图像变换是指将一幅图像变换为图像数据的另一种表现形式,例如将图像进行傅立叶变换,或者对图像进行X,Y方向的求导等,经过这些变换,可以将图像数据处理中的某些问题换一个别的角度想办法,所以图像变换是图像处理的时候比较常用的一种方法.

一.sobel算子

sobel算子是一个用于边缘检测的离散微分算子,其结合了高斯平滑和微分求导,用于计算图像灰度函数的近似梯度,在图像的任何一点使用该函数,都将产生对应的梯度矢量或者是发矢量,简单地说,sobel算子适用于计算出图像像素点之间变化幅度的算子,而边缘的变化幅度是最剧烈的,所以sobel算子能用来做边缘检测.

sobel算子分方向,在x,y方向指定阶数.

API:void sobel(输入源,输出,int 输出图像深度,int X方向差分阶数,int y方向差分阶数,int sobel邻域核大小,double 可选的缩放因子,double 可选的delata值,double 边界模式)

注:源图像和目标图像尺寸类型一致,,输出图像的深度根据源图像的深度决定,默认为-1,输出图像必须比源图像的数据更宽,sobel核大小默认为3,只能为1,3,5,7其中之一,缩放因子默认为-1,不缩放,delate值默认为.0

实际功能代码如下

Mat srcImage,sobelxImage,sobelxAbsImage,sobelyImage,sobelyAbsImage,dstImage;const int g_sobelCoreMax = 2;
int g_sobelCoreValue;const int g_deltaxMax = 9;
int g_deltaxValue;const int g_deltayMax = 9;
int g_deltayValue;void onTrackBarSobelCore(int pos,void* userData);
void onTrackBarSobelDeltax(int pos,void* userData);
void onTrackBarSobelDeltay(int pos,void* userData);int main(int argc,char* argv[])
{srcImage = imread("F:\\opencv\\OpenCVImage\\sobel.jpg");namedWindow("src image");namedWindow("sobelx image");namedWindow("sobely image");namedWindow("sobelxy image");g_sobelCoreValue = 0;g_deltaxValue = 0;g_deltayValue = 0;createTrackbar("core size", "src image", &g_sobelCoreValue, g_sobelCoreMax,onTrackBarSobelCore,0);createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarSobelDeltax,0);createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarSobelDeltay,0);onTrackBarSobelCore(g_sobelCoreValue, 0);imshow("src image", srcImage);moveWindow("src image", 0, 0);moveWindow("sobelx image", srcImage.cols, 0);moveWindow("sobely image", 0, srcImage.rows);moveWindow("sobelxy image", srcImage.cols, srcImage.rows);waitKey(0);return 0;
}void onTrackBarSobelCore(int pos,void* userData)
{int coreSize = g_sobelCoreValue*2+3;int deltax = g_deltaxValue+1;int deltay = g_deltayValue+1;Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);convertScaleAbs(sobelxImage, sobelxAbsImage);convertScaleAbs(sobelyImage, sobelyAbsImage);addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);imshow("sobelx image", sobelxAbsImage);imshow("sobely image", sobelyAbsImage);imshow("sobelxy image", dstImage);
}void onTrackBarSobelDeltax(int pos,void* userData)
{int coreSize = g_sobelCoreValue*2+3;int deltax = g_deltaxValue+1;int deltay = g_deltayValue+1;Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);convertScaleAbs(sobelxImage, sobelxAbsImage);convertScaleAbs(sobelyImage, sobelyAbsImage);addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);imshow("sobelx image", sobelxAbsImage);imshow("sobely image", sobelyAbsImage);imshow("sobelxy image", dstImage);
}void onTrackBarSobelDeltay(int pos,void* userData)
{int coreSize = g_sobelCoreValue*2+3;int deltax = g_deltaxValue+1;int deltay = g_deltayValue+1;Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);convertScaleAbs(sobelxImage, sobelxAbsImage);convertScaleAbs(sobelyImage, sobelyAbsImage);addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);imshow("sobelx image", sobelxAbsImage);imshow("sobely image", sobelyAbsImage);imshow("sobelxy image", dstImage);
}

  

当Ksize为1的时候,仅使用1*3内核或者3*1内核,而且没有平滑操作.

二.scharr算子

当sobel算子核大小为3的时候,因为计算使用的是导数的近似值,为了解决ksize为3的时候的误差问题,opencv引入了函数scharr,scharr和sobel一样快,但是结果更加精确

另外,对于sobel,因为目标图像的深度一般比源图像的深度更深,所以为了正常的显示目标图像,我们可以使用convertScalarAbs()函数,将深度缩放为八位数字图像,便于显示和保存.

API:void scharr(源图像,目标图像, int 输出图像深度,int X方向差分阶数,int y方向差分阶数 ,double 可选的缩放因子,double 可选的delata值,double 边界模式)

注:和sobel相比少了一个邻域核大小,因为默认为3

使用例程代码如下

Mat srcImage,scharrxImage,scharrxAbsImage,scharryImage,scharryAbsImage,dstImage;
const int g_deltaxMax = 0;
int g_deltaxValue;
const int g_deltayMax = 0;
int g_deltayValue;
void onTrackBarScharrDeltax(int pos,void* userData);
void onTrackBarScharrDeltay(int pos,void* userData);int main(int argc,char* argv[])
{srcImage = imread("F:\\opencv\\OpenCVImage\\scharr.jpg");namedWindow("src image");namedWindow("scharrx image");namedWindow("scharry image");namedWindow("scharrxy image");g_deltaxValue = 0;g_deltayValue = 0;createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarScharrDeltax,0);createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarScharrDeltay,0);onTrackBarScharrDeltax(g_deltaxValue,0);imshow("src image", srcImage);moveWindow("src image", 0, 0);moveWindow("scharrx image", srcImage.cols, 0);moveWindow("scharry image", 0, srcImage.rows);moveWindow("scharrxy image", srcImage.cols, srcImage.rows);waitKey(0);return 0;
}void onTrackBarScharrDeltax(int pos,void* userData)
{int deltax = g_deltaxValue+1;int deltay = g_deltayValue+1;Scharr(srcImage, scharrxImage, CV_16S, deltax, 0);Scharr(srcImage, scharryImage, CV_16S, 0, deltay);convertScaleAbs(scharrxImage, scharrxAbsImage);convertScaleAbs(scharryImage, scharryAbsImage);addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);imshow("scharrx image", scharrxAbsImage);imshow("scharry image", scharryAbsImage);imshow("scharrxy image", dstImage);
}
void onTrackBarScharrDeltay(int pos,void* userData)
{int deltax = g_deltaxValue+1;int deltay = g_deltayValue+1;Scharr(srcImage, scharrxImage, CV_16S, deltax, 0);Scharr(srcImage, scharryImage, CV_16S, 0, deltay);convertScaleAbs(scharrxImage, scharrxAbsImage);convertScaleAbs(scharryImage, scharryAbsImage);addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);imshow("scharrx image", scharrxAbsImage);imshow("scharry image", scharryAbsImage);imshow("scharrxy image", dstImage);
}

三.laplacian算子 (拉普拉斯算子)

有时候我们需要在X和y方向上同时差分,然后看整体的结果,这就需要用到laplacian算子,该算子是N维欧几里德空间中的二阶微分算子.

让一幅图的源图像减去其拉普拉斯算子的结果,图像的对比度将变得更强

API:void laplacian(源图像,目标图像,目标深度,int 邻域孔径尺寸,int 可选的缩放比例因子,int deleta可选值,int 边界模式);

注:图像深度和sobel一致,cv_8u对应cv_16s,ksize默认为1,且必须是正奇数.

实际上,laplacian是图像在x方向上的sobel算子和y方向上的sobel算子的和,使用这种算子之前,最好先进行图像的滤波操作,防止引入微笑误差.

使用代码

// lapacian拉普拉斯算子
Mat srcImage,srcImageGassianBlur,srcImageGray,laplacianImage,laplacianAbs;
const int g_coreSizeMax = 5;
int g_coreSizeValue;
void onTrackBarCoreSize(int pos,void* userData);int main(int argc,char* argv[])
{srcImage = imread("F:\\opencv\\OpenCVImage\\laplacian.jpg");GaussianBlur(srcImage, srcImageGassianBlur, Size(3,3), 0);cvtColor(srcImageGassianBlur, srcImageGray, CV_RGB2GRAY);namedWindow("src image");namedWindow("dst image");g_coreSizeValue = 0;createTrackbar("core size", "dst image", &g_coreSizeValue, g_coreSizeMax,onTrackBarCoreSize,0);onTrackBarCoreSize(g_coreSizeValue, 0);imshow("src image", srcImage);moveWindow("src image", 0, 0);moveWindow("dst image", srcImage.cols, 0);waitKey(0);return 0;
}void onTrackBarCoreSize(int pos,void* userData)
{int coreSize = g_coreSizeValue*2 + 1;Laplacian(srcImageGray, laplacianImage, CV_16S,coreSize);convertScaleAbs(laplacianImage, laplacianAbs);imshow("dst image", laplacianAbs);
}

四.canny边缘检测

边缘检测在工程上,有极大的应用,依靠边缘,确定物体的形状,检测产品的良好程度,canny算法,是opencv中提供的很不错的边缘检测算法,其检测边缘的步骤如下.

首先是滤波,使用高斯平滑滤波卷积降噪.然后是计算梯度幅值与方向,类似于sobel ,laplacian,第三是非极大值一致,排除掉不是边缘的像素,最后是之后阈值化,使用两个阈值,并且绑定的时候考虑颜色之间的关联关系(高低阈值的比例在1:2或者1:3之间).

API:void canny(输入图像,输出图像,double 低与阈值,double 高阈值,int sobel算子孔径,bool 计算梯度幅值标志);

注:sobel算子孔径默认为3,计算梯度幅值的标记默认为false,低阈值用于控制图像边缘的连接,而高阈值用于控制边缘的初始点位置.

另外,使用canny检测算法之前,最好先对图像经过一次降噪处理.

使用例程如下

//低̨ª阈D值¦Ì和¨ª高?阈D值¦Ì默?认¨?1:3
//sobel算?子Á¨®孔¡Á径?只?能¨¹取¨?值¦Ì 3 5 7
//平?滑?滤?波¡§算?子Á¨®孔¡Á径? 3,5,7,9
Mat srcImage,grayImage,grayBlurImage,cannyImage,dstImage;const int g_blurSizeMax = 3;//平?滑?滤?波¡§孔¡Á径?
int g_blurValue;
const int g_sobelSizeMax = 2;//sobel孔¡Á径?
int g_sobelValue;
const int g_lowThresholdMax = 80;//边À?缘¦Ì检¨¬测a低̨ª阈D值¦Ì
int g_lowThresholdValue;
int g_upThresholdValue;void onTrackBarBlurSize(int pos,void* userData);
void onTrackBarSobelSize(int pos,void* userData);
void onTrackBarLowThresholdSize(int pos,void* userData);int main(int argc,char* argv[])
{srcImage = imread("F:\\opencv\\OpenCVImage\\canny2.jpg");if(srcImage.channels() != 1){cvtColor(srcImage, grayImage, CV_BGR2GRAY);}else{grayImage = srcImage.clone();}namedWindow("src image");namedWindow("dst image");g_blurValue = 1;g_sobelValue = 1;g_lowThresholdValue = 3;g_upThresholdValue = 9;createTrackbar("blur size", "dst image", &g_blurValue, g_blurSizeMax,onTrackBarBlurSize,0);createTrackbar("sobel size", "dst image", &g_sobelValue, g_sobelSizeMax,onTrackBarSobelSize,0);createTrackbar("low threshold", "dst image", &g_lowThresholdValue, g_lowThresholdMax,onTrackBarLowThresholdSize,0);onTrackBarBlurSize(g_blurValue, 0);imshow("src image", srcImage);moveWindow("src image", 0, 0);moveWindow("dst image", srcImage.cols, 0);waitKey(0);return 0;
}void onTrackBarBlurSize(int pos,void* userData)
{int blurValue = g_blurValue*2 +3;int sobelValue = g_sobelValue*2 +3;if (g_lowThresholdValue == 0) {g_lowThresholdValue = 1;}int lowThresholdValue = g_lowThresholdValue;int upThresholdValue = lowThresholdValue*3;//平?滑?滤?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));//计?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);dstImage = Scalar::all(0);srcImage.copyTo(dstImage, cannyImage);imshow("dst image", dstImage);
}
void onTrackBarSobelSize(int pos,void* userData)
{int blurValue = g_blurValue*2 +3;int sobelValue = g_sobelValue*2 +3;if (g_lowThresholdValue == 0) {g_lowThresholdValue = 1;}int lowThresholdValue = g_lowThresholdValue;int upThresholdValue = lowThresholdValue*3;//平?滑?滤?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));//计?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);//用canny为掩码?,将src拷贝到dstimage中D,应为检测到的线条才会得到拷贝,所以,目标图上检测到的线条就会变成彩色条纹?dstImage = Scalar::all(0);srcImage.copyTo(dstImage, cannyImage);imshow("dst image", dstImage);
}void onTrackBarLowThresholdSize(int pos,void* userData)
{int blurValue = g_blurValue*2 +3;int sobelValue = g_sobelValue*2 +3;if (g_lowThresholdValue == 0) {g_lowThresholdValue = 1;}int lowThresholdValue = g_lowThresholdValue;int upThresholdValue = lowThresholdValue*3;//平?滑?滤?波¡§
   blur(srcImage, grayBlurImage, Size(blurValue,blurValue));//计?算?canny
   Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);dstImage = Scalar::all(0);srcImage.copyTo(dstImage, cannyImage);imshow("dst image", dstImage);
}

转载于:https://www.cnblogs.com/dengxiaojun/p/5252234.html

OPENCV图像变换-1相关推荐

  1. OpenCV图像变换(制作壁纸以及图像校正)

    在大多数情况下,我们手中图片的分辨率与显示器的最佳分辨率不一致,这个时候将其设置为壁纸往往效果会有所降低,我们可以通过OpenCV中的cv.resize()函数来实现. dst=cv2.resize( ...

  2. OpenCV修养(三)——图像处理(上)

    文章目录 致谢 3 图像处理(上) 3.1 几何变换 3.1.1 图像缩放 3.1.2 图像平移 3.1.3 图像旋转 3.1.4 仿射变换 3.2 图像阈值 3.3 图像平滑 3.3.1 图像噪声 ...

  3. 三:OpenCV图片颜色通道数据转换

    对图片进行操作时经常会涉及到不同通道数据提取,在OpenCV中提供了很多比较便捷的操作函数,本文涉及函数如下: 1.cvtColor 颜色空间转换 2.convertTo 图片数据类型转换 3.spl ...

  4. 仿射变换原理和其OpenCV-Python实现知识汇总

    ☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython ░ 一.仿射变换概念和类型 图像几何变换又称为图像空间变换,是各种图像处理算法的基础.它是在不 ...

  5. 4 用python进行OpenCV实战之图像变换1(平移)

    前言 到目前为止,经过前几节的介绍,我们已经有了一个坚实的基础去做一些图像处理,在本节我们先将介绍图像变换中的平移,为后面几节学习图像变换中的旋转.改变大小.镜像.裁剪打下一个好的基础 1 平移 1. ...

  6. 《OpenCV3编程入门》学习笔记7 图像变换(一)基于OpenCV的边缘检测

    第7章 图像变换 7.1 基于OpenCV的边缘检测 7.1.1 边缘检测的一般步骤 1.滤波:边缘检测算法主要基于图像强度的一阶和二阶导数,导数对噪声敏感,所以要滤波 2.增强:确定图像各点邻域强度 ...

  7. 干货 | OpenCV看这篇就够了,9段代码详解图像变换基本操作

    作者 | 王天庆,长期从事分布式系统.数据科学与工程.人工智能等方面的研究与开发,在人脸识别方面有丰富的实践经验.现就职某世界100强企业的数据实验室,从事数据科学相关技术领域的预研工作. 来源 |  ...

  8. OpenCV笔记之六(1)——图像处理之图像变换

    六.图像处理 本文中所有源代码均来自 Practical Python and OpenCV, 3rd Edition 的随书代码. (一)基础知识 1.图片类型 (1)位图(点阵图像) ​ 由像素组 ...

  9. OpenCV中的图像变换——傅里叶变换

    OpenCV中的图像变换--傅里叶变换 1. 效果图 2. 原理 3. 源码 3.1 Numpy实现傅里叶变换 3.2 OpenCV实现傅里叶变换 3.3 HPF or LPF? 参考 这篇博客将介绍 ...

最新文章

  1. 谷歌Waymo自建车厂,L4级无人车量产指日可待
  2. C++常见面试题之数据结构和算法
  3. java_web学习(8)会话与状态管
  4. php后台开发工具有哪些,热门的 PHP 开发工具都有哪些?
  5. 同级选择器_10-CSS3选择器详解
  6. Python和Java结合的项目实战_[项目实战] Python高级教程项目实战篇 Python和Java结合的项目实战 视频教程 [...
  7. 劲乐团u显示服务器维护,劲乐团9YOU原版服务端架设教程
  8. vscode上传GitHub
  9. 计算机组成原理课后答案(唐朔飞第三版) 第三章
  10. H5文章分享给好友或朋友圈后如何生成自定义分享内容
  11. word for mac 输入拼音时出现方框
  12. 单位元转换万元怎么转_元换算万元单位(元与万元的换算器)
  13. pytorch 语⾔模型数据集(周杰伦专辑歌词)数据集 免费
  14. 安全合规/法案--31--《数据安全法》原文及解读
  15. 开上新能源车之后,如何摆脱“充电焦虑”?
  16. 失踪61年的上帝之鸟重回美国阿肯色州 (组图)
  17. torch F.cosine_similarity使用
  18. 大邑移动团支部学校联谊活动
  19. html.dropdownlist必填,html.dropdownlist传值
  20. shell脚本自动化创建虚拟机的基本配置--tomcat--mysql--jdk--maven---妈妈再也不用担心我不会配置虚拟机了!

热门文章

  1. 后端技术:Java 泛型 T,E,K,V的含义,看完本文你就明白了?
  2. 操作系统基础:计算机作业管理知识笔记
  3. MongoDB高可用集群搭建
  4. python显示小数点后几位数_python窗口编程-3:数位处理(整数)
  5. 网络低俗词_从“低俗小说”中汲取7堂课,以创建有影响力的作品集
  6. 构建安全的Xml Web Service系列之如何察看SoapMessage
  7. 刚被IBM收购的红帽,它的下一站是中国
  8. 【SSH网上商城项目实战19】订单信息的级联入库以及页面的缓存问题
  9. 对AI"出错"零容忍?美国加强AI推理解释能力研究
  10. Finally语句块的运行