一、介绍

OpenCV(open source computer vision library)是一个基于BSD许可(开源)发行的跨平台计算机视觉库,它实现了图像处理和计算机视觉方面的很多通用算法,已成为计算机视觉领域最有力的研究工具。在这里我们要区分两个概念:图像处理和计算机视觉的区别:图像处理侧重于“处理”图像–如增强,还原,去噪,分割等等;而计算机视觉重点在于使用计算机来模拟人的视觉,因此模拟才是计算机视觉领域的最终目标。可以运行在Linux、Windows、Android和Mac OS操作系统上。

在计算机视觉项目的开发中,OpenCV作为较大众的开源库,拥有了丰富的常用图像处理函数库,采用C/C++语言编写,可以运行在Linux/Windows/Mac等操作系统上,能够快速的实现一些图像处理和识别的任务。
此外,OpenCV还提供了Java、python、cuda等的使用接口、机器学习的基础算法调用,从而使得图像处理和图像分析变得更加易于上手,让开发人员更多的精力花在算法的设计上。
————————————————

 发展史

 1 1.1 OpenCV发展历史
 2     OpenCV于1999年由Intel建立,如今由Willow Garage公司提供支持。
 3 
 4 OpenCV 0.X
 5     1999年1月,CVL项目启动。主要目标是人机界面,能被UI调用的实时计算机视觉库,为Intel处理器做了特定优化。
 6   2000年6月,第一个开源版本OpenCV alpha 3发布。
 7   2000年12月,针对linux平台的OpenCV beta 1发布。
 8 
 9 OpenCV 1.X
10     OpenCV 最初基于C语言开发,API也都是基于C的,面临内存管理、指针等C语言固有的麻烦。
11   2006年10月, 正式发布OpenCV 1.0版本,同时支持mac os系统和一些基础的机器学习方法,如神经网络、随机森林等,来完善对图像处理的支持。
12   2009年9月,OpenCV 1.2(beta2.0)发布。
13 
14 OpenCV 2.X
15     当C++流行起来,OpenCV 2.x发布,其尽量使用C++而不是C,但是为了向前兼容,仍保留了对C API的支持。
16   2009年9月2.0 beta发布,主要使用CMake构建。
17   2010年3月:2.1发布
18   2010年12月6日,OpenCV 2.2发布
19   2011年8月,OpenCV 2.3发布。
20   2012年4月2日,发布OpenCV 2.4.
21 
22 OpenCV 3.X
23     随着3.x的发布,1.x的C API将被淘汰不再被支持,以后C API可能通过C++源代码自动生成。3.x与2.x不完全兼容,与2.x相比,主要的不同之处在于OpenCV 3.x 的大部分方法都使用了OpenCL加速。
24   2014年8月, 3.0 alpha发布,除大部分方法都使用OpenCL加速外,3.x默认包含以及使用IPP(一套跨平台的软件函数库)
25   2017年8月,发布3.3版本,OpenCV开始支持C++ 11构建,同时加强对神经网络的支持。
26   OpenCV 4.X
27   2018年10月4.0.0发布,OpenCV开始需要支持C++11的编译器才能编译,同时对几百个基础函数使用"wide universal intrinsics"重写,极大改善了opencv处理图像的性能。

 

二、编译环境

  直接pip安装
    pip install opencv-python
  注意:
    1.安装的是opencv_python,但在导入的时候是import cv2。
    2.OpenCV依赖一些库,比如Numpy和matplotlib,先安装上。

 

三、图像基本操作

3.1 图像读取(cv.imread())与显示(cv.imshow() )以及保存(cv.imwrite()

 1 import cv2
 2 import matplotlib.pyplot as plt
 3 import numpy as np
 4 
 5 # 读取图像,这个函数返回图像数据,它是一个NumPy数组。
 6 image =cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\1.jpg')
 7 
 8 # 显示图像
 9 #cvtColor函数将图像从BGR颜色空间转换到RGB颜色空间。cv2.COLOR_BGR2RGB是转换的指定代码。
10 plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
11 # 如果命名为为中文,需要转码
12 plt.title('boy')
13 plt.axis('off')
14 plt.show()

----------------------------------------
ps:即使图像路径错误,它也不会抛出任何错误,但是打印 img会返回None

 保存图片

 1 import cv2 as cv
 2 import os
 3 
 4 print("当前工作目录:", os.getcwd())
 5 img = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\9.png', 0)
 6 cv.imshow('img', img)
 7 k = cv.waitKey(0)
 8 if k == 27:  # ESC 退出
 9     cv.destroyAllWindows()
10 elif k == ord('s'):  # 's' 保存退出
11     cv.imwrite(r'C:\Users\19225\PycharmProjects\test\src\user\static\new.png', img)
12     cv.destroyAllWindows()

 

3.2学习OpenCV中常见的图像操作,如调整大小、裁剪、旋转等。

 1 image =cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\1.jpg')
 2 
 3 # 这里展示了如何调整图像大小和进行裁剪
 4 resized_image = cv2.resize(image, (1000, 2000))
 5 cropped_image = image[50:150, 50:250]
 6 
 7 # 显示调整前的图像
 8 plt.imshow(cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB))
 9 plt.title('Resized Image')
10 plt.axis('off')
11 plt.show()
12 
13 # 显示裁剪后的图像
14 plt.imshow(cv2.cvtColor(cropped_image, cv2.COLOR_BGR2RGB))
15 plt.title('Cropped Image')
16 plt.axis('off')
17 plt.show()

 

 

3.3学习使用OpenCV进行边缘检测,掌握Canny边缘检测算法。

 1 image=cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\1.jpg')
 2 # 这里展示了如何使用Canny算法进行边缘检测
 3 edges = cv2.Canny(image, 100, 200)
 4 '''
 5 这行代码使用OpenCV的Canny函数进行边缘检测。Canny算法是一种非常流行的边缘检测算法,因为它能够很好地在噪声抑制和边缘检测之间取得平衡。
 6 该算法接受两个阈值参数(这里是100和200)来控制边缘检测的灵敏度。
 7 较低的阈值用于捕获较弱的边缘,而较高的阈值则用于最终边缘检测中需要更强边缘响应的场合。
 8 在Canny算法中,还会用到一种双阈值方法来检测强边缘和潜在的弱边缘,并通过强边缘来连接潜在的弱边缘,从而形成最终的边缘图像。
 9 '''
10 # 显示边缘检测结果
11 plt.imshow(edges, cmap='gray')
12 plt.title('Edge Detection')
13 plt.axis('off')
14 plt.show()
15 
16 
17 --------------------------
18 什么边缘检测
19     边缘检测是计算机视觉和图像处理中的一个基本步骤,它旨在识别图像中亮度变化明显的点。这些点通常对应于物体的边界,在图像中形成了物体的轮廓。边缘检测对于后续的图像分析、图像分割、特征提取等任务非常重要。通过边缘检测,我们可以从图像中提取出重要的结构信息,这些信息对于理解图像内容、进行目标识别等任务非常有用。

 

3.4学习如何使用OpenCV拼接图像---Numpy (np.hstack,np.vstack)

  只是简单地将几张图像直接堆叠而连成一张图像,并未对图像进行特征提取和边缘处理,因而并不能实现图像的全景拼接。

 1 retval = np.hstack(tup) # 水平拼接
 2 retval = np.vstack(tup) # 垂直拼接
 3 
 4 
 5 -----------------------
 6 代码示例
 7 # 读取要拼接的图片
 8 img = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\4.jpg')
 9 #调整图像大小
10 img = cv2.resize(img, None, fx=0.5, fy=0.5)  # 为了完整显示,缩小一倍
11 blur2 = cv2.blur(img, (2, 2))  # 模糊处理
12 blur3 = cv2.blur(img, (5, 5))
13 blur4 = cv2.blur(img, (10, 10))
14 
15 htich = np.hstack((img, blur2))
16 htich2 = np.hstack((blur3, blur4))
17 vtich = np.vstack((htich, htich2))
18 
19 # 显示图片
20 cv2.imshow("mergedDemo", vtich)
21 cv2.waitKey(0)
22 cv2.destroyAllWindows()

   方式二:matplotlib

    注意:opencv使用的是BGR模式,而matplotlib使用的是RGB模式,所以需要将opencv中的BGR、GRAY格式转换为RGB,使matplotlib中能正常显示opencv的图像。

 1 img1 = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\4.jpg', cv2.IMREAD_COLOR)  # 以彩色模式读取图片。这是默认模式
 2 img2 = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\5.jpg', cv2.IMREAD_GRAYSCALE)  # 以灰度模式读取图片
 3 img3 = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\6.jpg',
 4                   cv2.IMREAD_UNCHANGED)  # 包括alpha通道的完整图片将被读取
 5 img4 = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\3.jpg', cv2.IMREAD_ANYDEPTH)  # 读取图片,无论其深度如何
 6 # 将opencv中的BGR、GRAY格式转换为RGB,使matplotlib中能正常显示opencv的图像
 7 img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
 8 img2 = cv2.cvtColor(img2, cv2.COLOR_GRAY2RGB)
 9 img3 = cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)
10 img4 = cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)
11 plt.rcParams['font.sans-serif'] = ['FangSong']  # 支持中文标签
12 # 使用matplotlib的plt.subplot()和plt.imshow()函数将转换后的图片显示在一个2x2的子图网格中
13 plt.subplot(221), plt.title("img1"), plt.axis('off')
14 plt.imshow(img1)
15 plt.rcParams['font.sans-serif'] = ['FangSong']  # 支持中文标签
16 plt.subplot(222), plt.title("img2"), plt.axis('off')
17 plt.imshow(img2)
18 plt.rcParams['font.sans-serif'] = ['FangSong']  # 支持中文标签
19 plt.subplot(223), plt.title("img3"), plt.axis('off')
20 plt.imshow(img3)
21 plt.rcParams['font.sans-serif'] = ['FangSong']  # 支持中文标签
22 plt.subplot(224), plt.title("img4"), plt.axis('off')
23 plt.imshow(img4)
24 plt.show()

 

3.5图像打马赛克

1 import cv2
2 import numpy as np
3 
4 # 图像打码示例
5 censored_image = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\2.jpg')
6 censored_image[100:200, 200:300] = np.random.randint(0, 256, (100, 100, 3))
7 cv2.imshow('Censored Image', censored_image)
8 cv2.waitKey(0)
9 cv2.destroyAllWindows()

 

 

3.6 图像组合示例

 1 import cv2
 2 
 3 
 4 # 图像组合示例
 5 image_a = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\2.jpg')
 6 image_b = cv2.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\3.jpg')
 7 image_a[200:300, 300:500] = image_b[300:400, 500:700]
 8 cv2.imshow('Combined Image', image_a)
 9 cv2.waitKey(0)
10 cv2.destroyAllWindows()

 

3.7 图像加法

我们可以通过 OpenCV 函数,cv.add()或简单地通过 numpy 操作将两个图像相加,res = img1 + img2。两个图像应该具有相同的深度和类型,或者第二个图像可以是像素值,比如(255,255,255),白色值。

注意 OpenCV 相加操作和 Numpy 相加操作之间存在差异。OpenCV 添加是饱和操作,而 Numpy 添加是模运算。要注意的是,两种加法对于结果溢出的数据,会通过某种方法使其在限定的数据范围内。

 1 import numpy as np
 2 import cv2 as cv
 3 
 4 x = np.uint8([250])
 5 y = np.uint8([10])
 6 
 7 print(cv.add(x, y))  # 250 + 10 =260 => 255
 8 
 9 print(x + y)  # [4]
10 """
11 对于结果怎么样得到的:
12 1.print(cv.add(x, y)):
13 cv.add()是 OpenCV 中的函数,用于对两个图像或数组进行加法操作。
14 这里 x = np.uint8([250]) 和 y = np.uint8([10]),都是无符号 8 位整数类型的数组。
15 当进行 250 + 10 的计算时,结果是 260。但是由于无符号 8 位整数的取值范围是 0 到 255,所以 260 超出了这个范围。在这种情况下,OpenCV 的 cv.add() 函数会将结果截断为 255。
16 
17 2.print(x + y):
18 这里是使用 Python 的原生数组加法操作。
19 同样进行 250 + 10 的计算得到 260。但是对于无符号 8 位整数类型,当超出 255 的范围时,会发生溢出并从 0 重新开始计数。所以 260 - 256 = 4,最终结果为 [4]。
20 """

 

图像混合cv.addWeighted()

这也是将图像相加,但是对图像赋予不同的权重,从而给出混合感或透明感

通过在(0,1)之间改变的值, 可以用来对两幅图像或两段视频产生时间上的 画面叠化 (cross-dissolve)效果,就像在幻灯片放映和电影制作中那样

 1 import cv2 as cv
 2 
 3 img1 = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\6.jpg')
 4 img2 = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\5.jpg')
 5 
 6 dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)
 7 
 8 cv.imshow('dst', dst)
 9 cv.waitKey(0)
10 cv.destroyAllWindows()

 

性能测量和改进技术

在图像处理中,由于我们每秒需要处理大量操作,因此我们的代码不仅要提供正确的解决方案,还要以最快的方式提供,函数:cv.getTickCount,  cv.getTickFrequency

cv.getTickCount函数返回参考事件(如机器开启时刻)到调用此函数的时钟周期数。因此,如果在函数执行之前和之后调用它,则会获得用于执行函数的时钟周期数

cv.getTickFrequency函数返回时钟周期的频率,或每秒钟的时钟周期数。因此,要在几秒钟内找到执行时间

 1 import cv2 as cv
 2 from cffi.backend_ctypes import xrange
 3 
 4 img1 = cv.imread(r'C:\Users\19225\PycharmProjects\test\src\user\static\6.jpg')
 5 e1 = cv.getTickCount()
 6 for i in xrange(5, 49, 2):
 7     img1 = cv.medianBlur(img1, i)
 8 e2 = cv.getTickCount()
 9 t = (e2 - e1) / cv.getTickFrequency()
10 print(t)  # 2.6559413
11  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted on 2024-08-15 11:27  认真的六六  阅读(28)  评论(0编辑  收藏  举报