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

    何为冒泡事件?简单来说事件就像一个水里的泡泡,先触发当前对象再触发其父元素,然后是父元素的父元素... eg: <div class="out" onclick= " ...

  2. Spring中实现监听的方法

    在未使用框架进行编程的时候,我们常常在web.xml中加上这样一段话 <listener> <listener-class>XXX</listener-class> ...

  3. C++字符串(1)

    C++ 拼接字符串常量 C++允许拼接字符串字面值,即将两个用引号括起的字符串合并为一个.事实上,任何两个由空白(空格,制表符和换行符)分隔的字符串常量都将自动拼接成一个. 例子: cout < ...

  4. Hidden Word

    Hidden Word time limit per test 2 seconds memory limit per test 256 megabytes input standard input o ...

  5. iOS 判断奇偶数

    if (_bigUrlArray.count%2==0) {//如果是偶数 a = i*(_bigUrlArray.count/count);//每个线程图片初始数 b = (i+1)*(_bigUr ...

  6. Python中元素定位探讨

    以下以阿里云(10.10.1.11)系统中考试答题为例进行了python脚本的编写研究.模糊定位(定位一些动态值): ————————————————————————————————————————— ...

  7. python 第三章 字符串-例1

    1.字段宽度和精度 >>>'%.*s' % (10,'Gruido') '     Guido' >>>'%.-*s' % (10,'Gruido') 'Guido ...

  8. linux 显示文件或文件夹

    用 -v 很简单呀! 显示文件 ls -l | grep -v '^d'显示目录 ls -l | grep '^d'

  9. 用python计算md5,sha1,crc32

    Linux下计算md5sum,sha1sum,crc: 命令 输出 $md5sum hello f19dd746bc6ab0f0155808c388be8ff0  hello $sha1sum hel ...

  10. dfs+dp思想的结合------hdu1078

    首先是题目的意思: 从一个正方形的0,0点开始走,只能横着走,竖着走,最多走k步,下一个点的数一定要比当前这个点的值大,每走一步,就加上下一个点的数据,问数据最大能有多少. 首先遇到这种题目,走来走去 ...