图像变换是指将一幅图像变换为图像数据的另一种表现形式,例如将图像进行傅立叶变换,或者对图像进行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

实际功能代码如下

  1. Mat srcImage,sobelxImage,sobelxAbsImage,sobelyImage,sobelyAbsImage,dstImage;
  2.  
  3. const int g_sobelCoreMax = 2;
  4. int g_sobelCoreValue;
  5.  
  6. const int g_deltaxMax = 9;
  7. int g_deltaxValue;
  8.  
  9. const int g_deltayMax = 9;
  10. int g_deltayValue;
  11.  
  12. void onTrackBarSobelCore(int pos,void* userData);
  13. void onTrackBarSobelDeltax(int pos,void* userData);
  14. void onTrackBarSobelDeltay(int pos,void* userData);
  15.  
  16. int main(int argc,char* argv[])
  17. {
  18. srcImage = imread("F:\\opencv\\OpenCVImage\\sobel.jpg");
  19. namedWindow("src image");
  20. namedWindow("sobelx image");
  21. namedWindow("sobely image");
  22. namedWindow("sobelxy image");
  23.  
  24. g_sobelCoreValue = 0;
  25. g_deltaxValue = 0;
  26. g_deltayValue = 0;
  27. createTrackbar("core size", "src image", &g_sobelCoreValue, g_sobelCoreMax,onTrackBarSobelCore,0);
  28. createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarSobelDeltax,0);
  29. createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarSobelDeltay,0);
  30. onTrackBarSobelCore(g_sobelCoreValue, 0);
  31.  
  32. imshow("src image", srcImage);
  33. moveWindow("src image", 0, 0);
  34. moveWindow("sobelx image", srcImage.cols, 0);
  35. moveWindow("sobely image", 0, srcImage.rows);
  36. moveWindow("sobelxy image", srcImage.cols, srcImage.rows);
  37.  
  38. waitKey(0);
  39. return 0;
  40. }
  41.  
  42. void onTrackBarSobelCore(int pos,void* userData)
  43. {
  44. int coreSize = g_sobelCoreValue*2+3;
  45. int deltax = g_deltaxValue+1;
  46. int deltay = g_deltayValue+1;
  47. Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
  48. Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
  49. convertScaleAbs(sobelxImage, sobelxAbsImage);
  50. convertScaleAbs(sobelyImage, sobelyAbsImage);
  51. addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
  52. imshow("sobelx image", sobelxAbsImage);
  53. imshow("sobely image", sobelyAbsImage);
  54. imshow("sobelxy image", dstImage);
  55. }
  56.  
  57. void onTrackBarSobelDeltax(int pos,void* userData)
  58. {
  59. int coreSize = g_sobelCoreValue*2+3;
  60. int deltax = g_deltaxValue+1;
  61. int deltay = g_deltayValue+1;
  62. Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
  63. Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
  64. convertScaleAbs(sobelxImage, sobelxAbsImage);
  65. convertScaleAbs(sobelyImage, sobelyAbsImage);
  66. addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
  67. imshow("sobelx image", sobelxAbsImage);
  68. imshow("sobely image", sobelyAbsImage);
  69. imshow("sobelxy image", dstImage);
  70. }
  71.  
  72. void onTrackBarSobelDeltay(int pos,void* userData)
  73. {
  74. int coreSize = g_sobelCoreValue*2+3;
  75. int deltax = g_deltaxValue+1;
  76. int deltay = g_deltayValue+1;
  77. Sobel(srcImage, sobelxImage, CV_16S, deltax, 0,coreSize);
  78. Sobel(srcImage, sobelyImage, CV_16S, 0, deltay,coreSize);
  79. convertScaleAbs(sobelxImage, sobelxAbsImage);
  80. convertScaleAbs(sobelyImage, sobelyAbsImage);
  81. addWeighted(sobelxAbsImage, 0.5, sobelyAbsImage, 0.5, 0.0, dstImage);
  82. imshow("sobelx image", sobelxAbsImage);
  83. imshow("sobely image", sobelyAbsImage);
  84. imshow("sobelxy image", dstImage);
  85. }

  

当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

使用例程代码如下

  1. Mat srcImage,scharrxImage,scharrxAbsImage,scharryImage,scharryAbsImage,dstImage;
  2. const int g_deltaxMax = ;
  3. int g_deltaxValue;
  4. const int g_deltayMax = ;
  5. int g_deltayValue;
  6. void onTrackBarScharrDeltax(int pos,void* userData);
  7. void onTrackBarScharrDeltay(int pos,void* userData);
  8.  
  9. int main(int argc,char* argv[])
  10. {
  11. srcImage = imread("F:\\opencv\\OpenCVImage\\scharr.jpg");
  12. namedWindow("src image");
  13. namedWindow("scharrx image");
  14. namedWindow("scharry image");
  15. namedWindow("scharrxy image");
  16.  
  17. g_deltaxValue = ;
  18. g_deltayValue = ;
  19. createTrackbar("deltax value", "src image", &g_deltaxValue, g_deltaxMax,onTrackBarScharrDeltax,);
  20. createTrackbar("deltay value", "src image", &g_deltayValue, g_deltayMax,onTrackBarScharrDeltay,);
  21. onTrackBarScharrDeltax(g_deltaxValue,);
  22.  
  23. imshow("src image", srcImage);
  24. moveWindow("src image", , );
  25. moveWindow("scharrx image", srcImage.cols, );
  26. moveWindow("scharry image", , srcImage.rows);
  27. moveWindow("scharrxy image", srcImage.cols, srcImage.rows);
  28.  
  29. waitKey();
  30. return ;
  31. }
  32.  
  33. void onTrackBarScharrDeltax(int pos,void* userData)
  34. {
  35. int deltax = g_deltaxValue+;
  36. int deltay = g_deltayValue+;
  37. Scharr(srcImage, scharrxImage, CV_16S, deltax, );
  38. Scharr(srcImage, scharryImage, CV_16S, , deltay);
  39. convertScaleAbs(scharrxImage, scharrxAbsImage);
  40. convertScaleAbs(scharryImage, scharryAbsImage);
  41. addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);
  42. imshow("scharrx image", scharrxAbsImage);
  43. imshow("scharry image", scharryAbsImage);
  44. imshow("scharrxy image", dstImage);
  45. }
  46. void onTrackBarScharrDeltay(int pos,void* userData)
  47. {
  48. int deltax = g_deltaxValue+;
  49. int deltay = g_deltayValue+;
  50. Scharr(srcImage, scharrxImage, CV_16S, deltax, );
  51. Scharr(srcImage, scharryImage, CV_16S, , deltay);
  52. convertScaleAbs(scharrxImage, scharrxAbsImage);
  53. convertScaleAbs(scharryImage, scharryAbsImage);
  54. addWeighted(scharrxAbsImage, 0.5, scharryAbsImage, 0.5, 0.0, dstImage);
  55. imshow("scharrx image", scharrxAbsImage);
  56. imshow("scharry image", scharryAbsImage);
  57. imshow("scharrxy image", dstImage);
  58. }

三.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算子的和,使用这种算子之前,最好先进行图像的滤波操作,防止引入微笑误差.

使用代码

  1. // lapacian拉普拉斯算子
  2. Mat srcImage,srcImageGassianBlur,srcImageGray,laplacianImage,laplacianAbs;
  3. const int g_coreSizeMax = ;
  4. int g_coreSizeValue;
  5. void onTrackBarCoreSize(int pos,void* userData);
  6.  
  7. int main(int argc,char* argv[])
  8. {
  9. srcImage = imread("F:\\opencv\\OpenCVImage\\laplacian.jpg");
  10. GaussianBlur(srcImage, srcImageGassianBlur, Size(,), );
  11. cvtColor(srcImageGassianBlur, srcImageGray, CV_RGB2GRAY);
  12.  
  13. namedWindow("src image");
  14. namedWindow("dst image");
  15.  
  16. g_coreSizeValue = ;
  17. createTrackbar("core size", "dst image", &g_coreSizeValue, g_coreSizeMax,onTrackBarCoreSize,);
  18. onTrackBarCoreSize(g_coreSizeValue, );
  19.  
  20. imshow("src image", srcImage);
  21.  
  22. moveWindow("src image", , );
  23. moveWindow("dst image", srcImage.cols, );
  24.  
  25. waitKey();
  26. return ;
  27. }
  28.  
  29. void onTrackBarCoreSize(int pos,void* userData)
  30. {
  31. int coreSize = g_coreSizeValue* + ;
  32. Laplacian(srcImageGray, laplacianImage, CV_16S,coreSize);
  33. convertScaleAbs(laplacianImage, laplacianAbs);
  34. imshow("dst image", laplacianAbs);
  35. }

四.canny边缘检测

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

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

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

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

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

使用例程如下

  1. //低̨ª阈D值¦Ì和¨ª高?阈D值¦Ì默?认¨?1:3
  2. //sobel算?子Á¨®孔¡Á径?只?能¨¹取¨?值¦Ì 3 5 7
  3. //平?滑?滤?波¡§算?子Á¨®孔¡Á径? 3,5,7,9
  4. Mat srcImage,grayImage,grayBlurImage,cannyImage,dstImage;
  5.  
  6. const int g_blurSizeMax = ;//平?滑?滤?波¡§孔¡Á径?
  7. int g_blurValue;
  8. const int g_sobelSizeMax = ;//sobel孔¡Á径?
  9. int g_sobelValue;
  10. const int g_lowThresholdMax = ;//边À?缘¦Ì检¨¬测a低̨ª阈D值¦Ì
  11. int g_lowThresholdValue;
  12. int g_upThresholdValue;
  13.  
  14. void onTrackBarBlurSize(int pos,void* userData);
  15. void onTrackBarSobelSize(int pos,void* userData);
  16. void onTrackBarLowThresholdSize(int pos,void* userData);
  17.  
  18. int main(int argc,char* argv[])
  19. {
  20. srcImage = imread("F:\\opencv\\OpenCVImage\\canny2.jpg");
  21. if(srcImage.channels() != )
  22. {
  23. cvtColor(srcImage, grayImage, CV_BGR2GRAY);
  24. }
  25. else
  26. {
  27. grayImage = srcImage.clone();
  28. }
  29. namedWindow("src image");
  30. namedWindow("dst image");
  31. g_blurValue = ;
  32. g_sobelValue = ;
  33. g_lowThresholdValue = ;
  34. g_upThresholdValue = ;
  35. createTrackbar("blur size", "dst image", &g_blurValue, g_blurSizeMax,onTrackBarBlurSize,);
  36. createTrackbar("sobel size", "dst image", &g_sobelValue, g_sobelSizeMax,onTrackBarSobelSize,);
  37. createTrackbar("low threshold", "dst image", &g_lowThresholdValue, g_lowThresholdMax,onTrackBarLowThresholdSize,);
  38. onTrackBarBlurSize(g_blurValue, );
  39.  
  40. imshow("src image", srcImage);
  41.  
  42. moveWindow("src image", , );
  43. moveWindow("dst image", srcImage.cols, );
  44.  
  45. waitKey();
  46. return ;
  47. }
  48.  
  49. void onTrackBarBlurSize(int pos,void* userData)
  50. {
  51. int blurValue = g_blurValue* +;
  52. int sobelValue = g_sobelValue* +;
  53. if (g_lowThresholdValue == ) {
  54. g_lowThresholdValue = ;
  55. }
  56. int lowThresholdValue = g_lowThresholdValue;
  57. int upThresholdValue = lowThresholdValue*;
  58.  
  59. //平?滑?滤?波¡§
  60. blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
  61. //计?算?canny
  62. Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
  63. dstImage = Scalar::all();
  64. srcImage.copyTo(dstImage, cannyImage);
  65. imshow("dst image", dstImage);
  66. }
  67. void onTrackBarSobelSize(int pos,void* userData)
  68. {
  69. int blurValue = g_blurValue* +;
  70. int sobelValue = g_sobelValue* +;
  71. if (g_lowThresholdValue == ) {
  72. g_lowThresholdValue = ;
  73. }
  74. int lowThresholdValue = g_lowThresholdValue;
  75. int upThresholdValue = lowThresholdValue*;
  76.  
  77. //平?滑?滤?波¡§
  78. blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
  79. //计?算?canny
  80. Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
  81.  
  82. //用canny为掩码?,将src拷贝到dstimage中D,应为检测到的线条才会得到拷贝,所以,目标图上检测到的线条就会变成彩色条纹?
  83. dstImage = Scalar::all();
  84. srcImage.copyTo(dstImage, cannyImage);
  85. imshow("dst image", dstImage);
  86. }
  87.  
  88. void onTrackBarLowThresholdSize(int pos,void* userData)
  89. {
  90. int blurValue = g_blurValue* +;
  91. int sobelValue = g_sobelValue* +;
  92. if (g_lowThresholdValue == ) {
  93. g_lowThresholdValue = ;
  94. }
  95. int lowThresholdValue = g_lowThresholdValue;
  96. int upThresholdValue = lowThresholdValue*;
  97.  
  98. //平?滑?滤?波¡§
  99. blur(srcImage, grayBlurImage, Size(blurValue,blurValue));
  100. //计?算?canny
  101. Canny(grayBlurImage, cannyImage, lowThresholdValue, upThresholdValue,sobelValue);
  102. dstImage = Scalar::all();
  103. srcImage.copyTo(dstImage, cannyImage);
  104. imshow("dst image", dstImage);
  105. }

OPENCV图像变换-1的更多相关文章

  1. OpenCV图像变换(仿射变换与透视变换)

    仿射变换(affine transform)与透视变换(perspective transform)在图像还原.图像局部变化处理方面有重要意义.通常,在2D平面中,仿射变换的应用较多,而在3D平面中, ...

  2. OPENCV图像变换-2

    一.经典霍夫变换 霍夫变换是图像处理中的一种特征提取技术,该方法通过在一个参数空间中通过计算累计结果的局部最大值来得到一个符合该特定形状的集合,作为结果. 运用两个坐标空间之间的变换,将一个空间中具有 ...

  3. OpenCV —— 图像变换

    将一副图像转变成另一种表现形式 ,比如,傅里叶变换将图像转换成频谱分量 卷积 —— 变换的基础 cvFilter2D  源图像 src 和目标图像 dst 大小应该相同 注意:卷积核的系数应该是浮点类 ...

  4. python+opencv图像变换的两种方法cv2.warpAffine和cv2.warpPerspective

    本文链接:https://blog.csdn.net/qq_27261889/article/details/80720359 # usr/bin/env python # coding: utf- ...

  5. OpenCV图像变换二 投影变换与极坐标变换实现圆形图像修正

    投影变换 在放射变换中,物体是在二维空间中变换的.如果物体在三维空间中发生了旋转,那么这种变换就成为投影变换,在投影变换中就会出现阴影或者遮挡,我们可以运用二维投影对三维投影变换进行模块化,来处理阴影 ...

  6. <学习opencv>图像变换

    拉伸.收缩.扭曲和旋转 统一调整大小 我们经常会遇到一些我们希望转换为其他尺寸的图像. 我们可能想要扩大或缩小图像; 这两项任务都是由同一个功能完成的. cv::resize() 该cv::resiz ...

  7. [opencv]<学习Opencv>英文原版翻译学习

    [注]下文全部内容为 <<Learning OpenCV 3: Computer Vision in C++ with the OpenCV Library>>经由在线翻译整理 ...

  8. pyhton:图像旋转

    最近一个作业中要用到图像旋转,分享一下学习过程.如有讲错的地方,恳请指正! 图像旋转,想想真简单啊,不就是将图像矩阵乘上一个旋转平移矩阵就完了吗?实际上还真没这么简单.首先这个旋转平移矩阵怎么获得?通 ...

  9. OpenCV-Python Tutorials目录

    版本 3.4.6 1 Introduction to OpenCV OpenCV介绍Learn how to setup OpenCV-Python on your computer! 2 Gui F ...

随机推荐

  1. 【转】javascript Object使用Array的方法

    原文: http://www.cnblogs.com/idche/archive/2012/03/17/2403894.html Array.prototype.push push向数组尾部添加一项并 ...

  2. 1.1 python 安装(Windows)

    1.浏览器输入URL http://www.python.org/download/ https://www.python.org/downloads/release/python-2712/ Win ...

  3. java应用测试报告生成(二):利用ant的build.xml生成测试报告

    1.将写好的项目导出 在工程下会生成一个build.xml的蚂蚁图标的文件. 2.右击该文件,选择run as Ant build 其中的测试目录是可以选择的,如果涉及到顺序也可以调整顺序 3.执行后 ...

  4. 关于一些url中传递参数有空格问题

    1.关于一些url中传递参数有空格问题: url.replace(/ /g, "%20") 从上面的例子中可以看到可以用:replace(/ /g, "%20" ...

  5. 学习笔记——工厂模式Factory

    Product是我们所需要获得的对象,一般的使用中,我们直接通过new获得新对象. 当需要大量获得对象时,每一次都new会很麻烦. <真菌世界>游戏中,一个星球上有很多树,一棵树会不断生成 ...

  6. jsp导入外部样式

    在博客园遇到一位朋友,她将我的代码下载下去,运行的时候,jsp页面的样式不存在,不会显示出来. 这里就将我之前写的SpringSpringmvcMybatis做一些修改. jdk1.8 加入了两个ja ...

  7. 使用MyBatis的Generator自动创建实体类和dao的接口与xml

    在实际的项目中其实建立数据库和设计数据库的时候特别重要,而等数据库设计完成之后,根据数据库创建实体类的工作就特别麻烦和繁琐了,不仅很麻烦,而且很浪费时间,不做又不行,这次就找到了一个简单的方法可以让m ...

  8. 【将txt文本转图片】

    [测试类] public static void main(String[] args) { try { File textFile = new File("F:\\java56班\\ecl ...

  9. 完整的 HTML 4 + HTML 5 实体参考手册

    1 完整的 HTML 4 + HTML 5 实体参考手册 http://www.runoob.com/charsets/html-charsets.html 1 下表中的所有实体都能在所有的浏览器中正 ...

  10. script 两则

    script1: PATH=/usr/local/bin:/usr/bin:$PATH:. . $HOME/utility/macro/macro.env OVO_DIR=/tmp LOGFILE=$ ...