【OpenCV】使用笔记

OpenCV使用疑难点记录

楼主推荐的opencv中文教程的学习
opencv-python原版教程

基本概念

  • using namespace cv:如果希望不要每次都输入 cv:: ,则可使用这个语句
  • IplImage和Mat的区别:IplImage使用的是C结构,而Mat使用的是C++结构,前者需要手动释放内存,后者不需要。而Mat 是 OpenCV 中用来表示图像的多维数组,类似 tensorflow 和 pytorch 中的 tensor。
  • cv2.imread读取的RGB图片是BGR格式的,这是因为但是流行,所以一直沿用下来了哈哈哈哈哈哈哈
  • cv2.cvtColor(image, cv2.COLOR_BGR2RGB),不同颜色的格式的转换
  • 灰度转换公式 = 0.2126 * R + 0.7152 * G + 0.0722 * B
  • HSV:色调(H),饱和度(S),明度(V)参考链接

Gui 特性

  • 先创建一个窗口,之后再加 载 图 像。这种情况下,你可以决定窗口是否可以调整大小。 使用到函数是cv2.namedWindow()。 初 始 设 定 函 数标 签 是 cv2.WINDOW_AUTOSIZE。 但是如果你把标 签改成cv2.WINDOW_NORMAL,你就可以调整窗口大小了。当图像维度太大,或者要添加轨迹条时,调整窗口大小将会很有用。
  • 视频的调用:cv2.VideoCapture(0)一般为零就是调用本机的摄像头,也可以调用本地的视频文件
  • 窗口滑条的使用:cv2.getTrackbarPos()  第一个参数是滑动条的名字;第二个参数是滑动条被放置窗口的名字;第三个参数是滑动条的默认位置;第四个参数是滑动条的最大值;cv2.setMouseCallback返回鼠标的操作

核心操作

  • 为图像扩边(填充): cv2.copyMakeBorder()
  • 图像混合和加法:加法cv2.add(x,y),混合:cv2.addWeighted,两者本质也是加法,只是两幅图的权重不同,混合后会形成透明效果
  • 效率检测:cv2.getTickCount 函数返回从参考点到这个函数被执行的时钟数。所以当你在一个函数执行前后都调用它的话,你就会得到这个函数的执行时间(时钟数)。cv2.getTickFrequency 返回时钟频率,或者说每秒钟的时钟数。所以你可以按照下面的方式得到一个函数运行了多少秒。
  • 图像放缩:cv2.resize:1)INTER_NEAREST - 最近邻插值法,2)INTER_LINEAR - 双线性插值法(默认),3)INTER_AREA - 基于局部像素的重采样(resampling using pixel area relation)。对于图像抽取(image decimation)来说,这可能是一个更好的方法。但如果是放大图像时,它和最近邻法的效果类似。,4)INTER_CUBIC - 基于4x4像素邻域的3次插值法,5)INTER_LANCZOS4 - 基于8x8像素邻域的Lanczos插值
  • 平移: 构造平移矩阵传给:cv2.warpAffine()
    在这里插入图片描述
  • 旋转:(默认是逆时针哦)在这里插入图片描述
    构造旋转矩阵M=cv2.getRotationMatrix2D((cols/2,rows/2),45,0.6)
    dst=cv2.warpAffine(img,M,(2cols,2rows))(第三个参数是输出图像的尺寸中心)
  • 仿射变换仿射变换是一种二维座标到二维座标之间的线性变换。 在仿射变换中,原图中所有的平行线在结果图像中同样平行。为了创建这个矩阵我们需要从原图像中找到三个点以及他们在输出图像中的位置。cv2.getAffineTransform 同样会创建一个 2x3 的矩阵,最后这个矩阵会被传给函数 cv2.warpAffine
  • 透视变换(投影变换)透视变换是将图片投影到一个新的视平面,也称作投影映射.它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射。 对于视角变换,我们需要一个 3x3 变换矩阵。在变换前后直线还是直线。要构建这个变换矩阵,你需要在输入图像上找 4 个点,以及他们在输出图像上对应的位置。这四个点中的任意三个都不能共线。这个变换矩阵可以有函数 cv2.getPerspectiveTransform() 构建。然后把这个矩阵传给函数cv2.warpPerspective。
  • 图像阈值: 在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
    这种方法需要我们指定三个参数,返回值只有一个。
      • Adaptive Method- 指定计算阈值的方法。
      – cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
      – cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。
      • Block Size - 邻域大小(用来计算阈值的区域大小)。
      • C - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。
  • Otsu’ ’s 二值化:这里用到到的函数还是 cv2.threshold(),但是需要多传入一个参数(flag):cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值与设定的阈值相等。

图像滤波

  • 平均: 这是由一个归一化卷积框完成的。他只是用卷积框覆盖区域所有像素的平均值来代替中心元素。可以使用函数 cv2.blur() 和 cv2.boxFilter() 来完这个任务。需要设定卷积框的宽和高:1/9*ones(3,3)。
    注意:如果不想使用归一化卷积框,应该使用 cv2.boxFilter(),这时要传入参数 normalize=False。

  • 高斯模糊: 卷积核换成高斯核(简单来说,方框不变,将原来每个方框的值是相等的,现在里面的值是符合高斯分布的,方框中心的值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包。原来的求平均数现在变成求加权平均数,全就是方框里的值)。实现的函数是 cv2.GaussianBlur()。我们需要指定高斯核的宽和高(必须是奇数)。以及高斯函数沿 X,Y 方向的标准差。如果我们只指定了 X 方向的的标准差,Y 方向也会取相同值。如果两个标准差都是 0,那么函数会根据核函数的大小自己计算。高斯滤波可以有效的从图像中去除高斯噪音。也可以使用函数 cv2.getGaussianKernel() 自己构建一个高斯核。

  • 形态学转换: 腐蚀cv2.erode(img,kernel,iterations = 1);膨胀cv2.dilate(img,kernel,iterations = 1);先进性腐蚀再进行膨胀就叫做开运算cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel);闭运算先膨胀再腐蚀。它经常被用来填充前景物体中的小洞,或者前景物体上的小黑点。cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel);

  • 形态学梯度其实就是一幅图像膨胀与腐蚀的差别。结果看上去就像前景物体的轮 cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel);礼帽原始图像与进行开运算之后得到的图像的差;黑帽进行闭运算之后得到的图像与原始图像的差。

  • 图像梯度 :Sobel 算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。你可以设定求导的方向(xorder 或 yorder)。还可以设定使用的卷积核的大小(ksize)。如果 ksize=-1,会使用 3x3 的 Scharr 滤波器,它的的效果要比 3x3 的 Sobel 滤波器好(而且速度相同,所以在使用 3x3 滤波器时应该尽量使用 Scharr 滤波器)

  • 边界检测 :cv2.Canny()需要设置滞后阈值的最大最小值;当图像的灰度梯度高于 maxVal 时被认为是真的边界,那些低于 minVal 的边界会被抛弃。如果是位于中间的话,就需要判断他是不是与maxVal是相连的。

  • 图像金字塔:Gaussian pyramid:cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金子塔(尺寸变小,分辨率降低)。 Laplacian Pyramid:函数 cv2.pyrUp() 从一个低分辨率小尺寸的图像向下构建一个金子塔(尺寸变大,但分辨率不会增加)

  • 直方图均衡化:

img = cv2.imread('wiki.jpg',0)
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ)) #stacking images side-by-side
cv2.imwrite('res.png',res)
  • CLAHE: 自适应的直方图均衡化。这种情况下,整幅图像会被分成很多小块,这些小块被称为“tiles”(在 OpenCV 中 tiles 的大小默认是 8x8),然后再对每一个小块分别进行直方图均衡化
  • 2D 直方图:以上直方图均衡化、CLAHE都是一维直方图,之所以称为一维,是因为我们只考虑了图像的一个特征:灰度值。但是在 2D 直方图中我们就要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要考虑每个的颜色(Hue)和饱和度(Saturation)。
  • 直方图反向投影:输出与输入图像(待搜索)同样大小的图像,其中的每一个像素值代表了输入图像上对应点属于目标对象的概率。用更简单的话来解释,输出图像中像素值越高(越白)的点就越可能代表我们要搜索的目标(在输入图像所在的位置)。这是一个直观的解释。直方图投影经常与 camshift算法等一起使用。

图像特征提取与描述(单独开一集吧。。。)

  • 众多的角点检测方法:Harris、Shi-Tomasi、SIFT、SURF、FAST、BRIEF、ORB
  • cv2.cornerSubPix(),它可以提供亚像素级别的角点检测。下面是一个例子。首先我们要找到 Harris角点,然后将角点的重心传给这个函数进行修正
  • cv2.cornerHarris(gray,2,3,0.04)输入图像,用sobel算子求得区域的梯度,再对区域打分,高分的就是角点。
    cv2.goodFeaturesToTrack()是Harris的改进版,如果导数矩阵的两个特征值的打分超过阈值,才会判定他是角点。
    cv2.cornerHarris和cv2.goodFeaturesToTrack都有旋转不变特性,但是对于放大和缩小的图像就不行了。
  • SIFT 不同尺度使用不同的检测窗口,尺度空间滤波器可以使用一些列具有不同方差 σ 的高斯卷积核构成;然后使用 2x2 的 Hessian 矩阵计算主曲率虑去那些没用的边界,剩下关键的点;每一个关键点赋予一个反向参数,这样它才会具有旋转不变性。获取关键点(所在尺度空间)的邻域,然后计算这个区域的梯度级和方向。根据计算得到的结果创建一个含有 36 个 bins(每 10 度一个 bin)的方向直方图。(使用当前尺度空间 σ 值的 1.5 倍为方差的圆形高斯窗口和梯度级做权重)。直方图中的峰值为主方向参数,如果其他的任何柱子的高度高于峰值的80% 被认为是辅方向。这就会在相同的尺度空间相同的位置构建除具有不同方向的关键点。最后采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量,取第一个图的某个关键点,通过遍历找到第二幅图像中的距离最近的那个关键点完成匹配。
  • SURF使用盒子滤波器(box_filter)对 LoG 进行近似。第二就是主方向为最大的 Haar 响应累加值对应的方向。
  • 图像特征提取与描述官方翻译的说明1
    图像特征提取与描述官方翻译的说明2

视频分析

  • meanshift和camshift: 要在 OpenCV 中使用 Meanshift 算法首先我们要对目标对象进行设置,计算目标对象的直方图,这样在执行 meanshift 算法时我们就可以将目标对象反向投影到每一帧中去了。另外我们还需要提供窗口的起始位置。在这里我们值计算 H(Hue)通道的直方图,同样为了避免低亮度造成的影响,我们使用函数 cv2.inRange() 将低亮度的值忽略掉。与 Meanshift 基本一样,但是返回的结果是一个带旋转角度的矩形(这是我们的结果),以及这个矩形的参数

**重投影** ``` for i in xrange(len(objpoints)): imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist) error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2) tot_error += error ```

杂问

  • cap = cv2.VideoCapture(0)#获取视频的控制权
    cap.release()#结束视频的控制权 释放这个进程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章