Python学习|2021-9-21 opencv学习

Python学习|2021-9-21 opencv学习
文章图片


opencv学习日志

  • 关于Anaconda安装cv2
    • 先错误示范一下
    • 正确方法,亲测有效
  • Opencv基本使用方法
    • 图像的读取、显示和保存
      • 图像的读取和显示
      • 图像的保存
    • 像素处理
      • 读取像素
      • 修改像素值
  • 使用numpy方法进行像素处理
    • 读取像素
    • 修改像素值
  • 访问图像属性
    • 图像的形状
    • 图像的总像素数
    • 图像的数据类型
  • ROI(region of interest),感兴趣区域。
    • 提取
    • 复制
  • 拆分和合并通道
    • 拆分通道(split)
    • 合并通道(merge)
  • 制作图像边界(填充)(cv2.copyMakeBorder())
    • 函数参数详解
    • 使用方法示例
  • 图像的算术运算
    • 图像加法 (cv2.add())
    • 图像混合 (cv2.addWeighted())
    • 按位运算
  • 图像类型转换
    • BGR图像转RGB图像
    • BGR图像转灰度图
    • 灰度图转BGR图像
    • 灰度图转RGB图像

关于Anaconda安装cv2 在学习opencv前,我们首先要安装opencv的库函数。
先错误示范一下
  1. 首先我们在Anaconda Prompt窗口输入下列命令:
conda install opencv-python

【Python学习|2021-9-21 opencv学习】然后就会出现报错:
PackagesNotFoundError: The following packages are not available from current channels:
  • python-opencv
Current channels:
  • https://repo.anaconda.com/pkgs/main/win-64
  • https://repo.anaconda.com/pkgs/main/noarch
  • https://repo.anaconda.com/pkgs/r/win-64
  • https://repo.anaconda.com/pkgs/r/noarch
  • https://repo.anaconda.com/pkgs/msys2/win-64
  • https://repo.anaconda.com/pkgs/msys2/noarch
To search for alternate channels that may provide the conda package you’re
looking for, navigate to https://anaconda.org and use the search bar at the top of the page.
这个大概就是现在opencv库不支持这样安装了,需要我们找到对应的版本进行安装
  1. 我们在Anaconda Prompt窗口输入下列命令:
conda install --channel https://conda.anaconda.org/menpo opencv

安装过程出错PermissionError
大概原因是有一些文件被anaconda(或其他一些进程)锁定,opencv可能需要读写这个文件
正确方法,亲测有效 关闭anaconda,spyder的所有相关进程。
先在Anaconda Prompt窗口输入如下命令:
conda update --all

然后就会出现一些要更新的包,下载的包什么的,反正全部yes就行了
再在Anaconda Prompt窗口输入如下命令:
conda install --channel https://conda.anaconda.org/menpo opencv

过一会儿也会让你输入[y/n]:
直接y就行了。等命令执行完anaconda也就安装好cv2库了
Opencv基本使用方法 Anaconda的代码提醒太慢了,我还是用pycharm,上面的只是给使用Anaconda的童鞋们看的。
图像的读取、显示和保存 图像的读取和显示
import cv2img = cv2.imread("D:/conda programs/snack2.png") # 读取图像文件(完整文件名) # cv2.namedWindow("she") # 为窗口命名(其实不需要,下面显示图像的时候也要给窗口命名) cv2.imshow("she", img) # 显示图像。第一个参数是窗口名,第二个参数就是刚才读入的图像 cv2.waitKey(0) # 参数为窗口等待时间,如果没有这行代码没有,会直接一闪而过。 # 当该参数值小于0时,为等待单击。 参数大于0时,为等待时间。 参数等于0或没有参数则无限等待。 cv2.destroyAllWindows() # 销毁所有窗口,不再占用内存。

注意:python读取和保存文件名中间的分割符与Windows默认的“\”不一样,python读取保存图像中间的分隔符为“/”或“\”
便可以显示图片啦!(姐姐)

图像的保存
cv2.imwrite("C:/Users/Zhang-Lei/Desktop/snack.png", img) # 保存图像。参数为要保存的完整文件名和读入的图像

这样就成功保存在桌面啦
Python学习|2021-9-21 opencv学习
文章图片

像素处理 读取像素
  1. 灰度图像 img[x, y] : 单通道图像
我将上面的图像转为灰度图,保存为"C:/Users/Zhang-Lei/Desktop/snack_gray.png",然后读取其中某个点的像素值
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png") pixel = img[100, 100] print(pixel)

结果:
Python学习|2021-9-21 opencv学习
文章图片

结果为什么会是三个数字呢?
opencv读取图像时会改变图片的格式。
那么如何读取图像时不改变图片格式呢?
读取图像时加入参数cv2.IMREAD_UNCHANGED
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png", cv2.IMREAD_UNCHANGED) pixel = img[100, 100] print(pixel)

结果:
Python学习|2021-9-21 opencv学习
文章图片

这样就是真正的单通道图片啦!
  1. BGR图像 img[x, y, z]
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") blue_pixel = img[100, 100, 0]# 第三个参数代表通道数,0表示blue通道 green_pixel = img[100, 100, 1]# 1表示green通道 red_pixel = img[100, 100, 2]# 2表示red通道 print(blue_pixel, '\n', green_pixel, '\n', red_pixel)```

结果:
Python学习|2021-9-21 opencv学习
文章图片

即三通道的像素值分别为139, 160, 188
修改像素值
  1. 分通道处理
img[100, 100, 0] = 255 img[100, 100, 1] = 255 img[100, 100, 2] = 255 print(img[100, 100])

分别将三个通道的像素值都设置为255
结果:
Python学习|2021-9-21 opencv学习
文章图片

  1. 三通道同时处理
img[100, 100] = [0, 0, 0] print(img[100, 100])

同时将三通道的像素值都设置为0
结果:
Python学习|2021-9-21 opencv学习
文章图片

3. 区域像素赋值
img[100:150, 100:150] = [255, 255, 255] cv2.imshow("she", img) cv2.waitKey() cv2.destroyAllWindows()

显示结果:
区域内的所有通道像素值都是255,因此该区域为白色。
Python学习|2021-9-21 opencv学习
文章图片

使用numpy方法进行像素处理 读取像素
blue = img.item(100, 100, 0) green = img.item(100, 100, 1) red = img.item(100, 100, 2) print(blue, '\n', green, '\n', red)

结果:
Python学习|2021-9-21 opencv学习
文章图片

同样可以获取到三通道各自的像素值
注意,彩色图不可以直接使用item查看三通道的像素值,否则会报错,报错如下:
incorrect number of indices for array
修改像素值
img.itemset((100, 100, 0), 255) img.itemset((100, 100, 1), 255) img.itemset((100, 100, 2), 255) print(img.item(100, 100, 0)) print(img.item(100, 100, 1)) print(img.item(100, 100, 2))

结果:
Python学习|2021-9-21 opencv学习
文章图片

可以看到像素值改变了
访问图像属性 图像的形状
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") print(img.shape)

结果:
Python学习|2021-9-21 opencv学习
文章图片

960行*640列, 三通道彩色图
图像的总像素数
print(img.size)

结果:
Python学习|2021-9-21 opencv学习
文章图片

960 * 640 = 1843200
图像的数据类型
print(img.dtype)

结果:
Python学习|2021-9-21 opencv学习
文章图片

关于数据类型,整型浮点型里面还有细分,这里就不多说了。
ROI(region of interest),感兴趣区域。 提取
cv2.imshow("face", img[100:400, 200:400]) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

可以看到提取了脸部图像
复制 下面我们将脸部图像复制到图像的下方
img[500:800, 200:400] = img[100:400, 200:400] cv2.imshow("demo", img) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

拆分和合并通道 拆分通道(split)
b, g, r = cv2.split(img) cv2.imshow("blue", b) cv2.imshow("green", g) cv2.imshow("red", r) cv2.waitKey() cv2.destroyAllWindows()

结果:

可以看到,b, g, r三通道的图像都被提取了出来
注意:cv.spilt()是一项代价高昂的操作(就时间而言)。所以只有在你需要时才这样做,否则就使用 Numpy 索引。
即:
b = img[:, :, 0] g = img[:, :, 1] r = img[:, :, 2]

合并通道(merge)
new_img = cv2.merge((b, g, r)) cv2.imshow("new", new_img) cv2.waitKey() cv2.destroyAllWindows()

结果:

可以看到,三通道的图片合并在一起成了一张新图片。
制作图像边界(填充)(cv2.copyMakeBorder()) 应用于在图像周围创建边框,例如相框效果。
函数参数详解 cv2.copyMakeBorder(src, top, bottom, left, right, borderType, [value])
  • src : 输入的图像。
  • top, bottom, left, right : 上下左右四个方向上的边界拓宽的值。
  • borderType : 指定边框类型。
  • value:当borderType的类型是cv2.BORDER_CONSTANT时,则这个值即为要设置的边框颜色 注意:使用matplotlib展示图像时这里的三通道的顺序是RGB,而不是BGR
borderType的类型可以是如下几种:
  • cv2.BORDER_CONSTANT :添加一个恒定的彩色边框。该值应作为下一个参数value给出。
  • cv2.BORDER_REFLECT :边框将是边框元素的镜像反射,如下所示:fedcba|abcdefgh|hgfedcb
  • cv2.BORDER_REFLECT_101或者 cv.BORDER_DEFAULT :与上面相同,但略有改动,如下所示: gfedcb | abcdefgh | gfedcba
  • cv2.BORDER_REPLICATE : 最后一个元素被复制,如下所示: aaaaaa | abcdefgh | hhhhhhh
  • cv2.BORDER_WRAP :不好解释,它看起来像这样: cdefgh | abcdefgh | abcdefg
使用方法示例
import cv2 import matplotlib.pyplot as pltimg = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png") Blue = [0, 0, 255] replicate = cv2.copyMakeBorder(img, 100, 100, 100, 100, cv2.BORDER_REPLICATE) reflect = cv2.copyMakeBorder(img, 100, 100, 100, 100, cv2.BORDER_REFLECT) reflect101 = cv2.copyMakeBorder(img, 100, 100, 100, 100, cv2.BORDER_DEFAULT) wrap = cv2.copyMakeBorder(img, 100, 100, 100, 100, cv2.BORDER_WRAP) constant = cv2.copyMakeBorder(img, 100, 100, 100, 100, cv2.BORDER_CONSTANT, value=https://www.it610.com/article/Blue)plt.figure(figsize=(12, 12))plt.subplot(2, 3, 1) plt.imshow(img) plt.title("Original")plt.subplot(2, 3, 2) plt.imshow(replicate) plt.title("Replicate")plt.subplot(2, 3, 3) plt.imshow(reflect) plt.title("Reflect")plt.subplot(2, 3, 4) plt.imshow(reflect101) plt.title("Reflect101")plt.subplot(2, 3, 5) plt.imshow(wrap) plt.title("Wrap")plt.subplot(2, 3, 6) plt.imshow(constant) plt.title("Constant")plt.show()

结果:

可以看到除了第一张初始图象外,其他五张的边界都发生了一些变化。
图像的算术运算 图像加法 (cv2.add()) 结果图像=图像1+图像2
通过 OpenCV 函数,cv2.add()或简单地通过 numpy 操作将两个图像相加,res = img1 + img2。两个图像应该具有相同的深度和类型,或者第二个图像可以是像素值,比如(255,255,255),白色值。
图像操作代码示例:
img = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack_gray.png') img_add1 = cv2.add(img, img) img_add2 = img + img cv2.imshow('original', img) cv2.imshow('add1', img_add1) cv2.imshow('add2', img_add2) cv2.waitKey() cv2.destroyAllWindows()

结果:

注意:注OpenCV相加操作和 Numpy 相加操作之间存在差异。OpenCV 添加是饱和操作,而 Numpy 添加是模运算。要注意的是,两种加法对于结果溢出的数据,会通过某种方法使其在限定的数据范围内。
代码示例:
import cv2 import numpy as npx = np.uint8([250]) y = np.uint8([10]) print(cv2.add(x, y)) print(x + y)

结果:
Python学习|2021-9-21 opencv学习
文章图片

cv2.add()操作中:250+10 = 260 > 255 => 255
直接相加操作中:(250+10)% 256 = 4
图像混合 (cv2.addWeighted()) 结果图像=图像1*系数1+图像2*系数2+亮度调节量
cv.addWeighted(src1, alpha, src2, beta, gamma)
注意:参数gamma不能省略
也就是将图像相加,但是对图像赋予不同的权重,从而给出混合感或透明感。
注意:这里想要混合的两个图像尺寸,类型必须完全相同,否则将报错。
报错如下:
error: (-209:Sizes of input arguments do not match) The operation is neither ‘array op array’ (where arrays have the same size)
代码示例:
img1 = cv2.imread('C:/Users/Zhang-Lei/Desktop/5.jpg') img2 = cv2.imread('C:/Users/Zhang-Lei/Desktop/6.jpg') res = cv2.addWeighted(img1, 0.3, img2, 0.7, 0) cv2.imshow('img1', img1) cv2.imshow('img2', img2) cv2.imshow('res', res) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

可以看到,两个图像按照一定的比例融合在一起。
按位运算 这包括按位 AND(与),OR(或),NOT(非) 和 XOR(异或) 运算。它们在提取图像的某一部分、定义和使用非矩形 ROI 等方面非常有用。
假如我想加一个OpenCV的 logo在一个图像上,如果只是简单的将两张图像想加,则会改变叠加处的颜色。如果进行上面所说的混叠操作,则会得到一个有透明效应的结果,但我希望得到一个不透明的logo。如果logo是一个矩形logo,那可以用上节所讲的ROI来做。但是OpenCV的logo是不规则形状的,所以用下面的bitwise操作来进行。
img1 = cv2.imread('C:/Users/Zhang-Lei/Desktop/snack.png') img2 = cv2.imread('C:/Users/Zhang-Lei/Desktop/opencv.jpg') rows, cols, channels = img2.shape roi = img1[:rows, :cols] img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(img2gray, 200, 255, cv2.THRESH_BINARY)# 二值化,使ROI中的徽标区域变黑 cv2.imshow('mask', mask) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

可见图片已经二值化,只有黑白两部分了。
mask_inv = cv2.bitwise_not(mask)# 非运算,黑白反转 cv2.imshow('mask_inv', mask_inv) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

可见,与上图相比黑白发生反转。
img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv) img2_fg = cv2.bitwise_and(img2, img2, mask=mask_inv) cv2.imshow('img1_bg', img1_bg) # 仅从徽标图像中获取徽标区域。 cv2.imshow('img2_fg', img2_fg) # 在ROI 中放置徽标并修改主图像 cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

res = cv2.add(img1_bg, img2_fg) img1[:rows, :cols] = res cv2.imshow('res', res) cv2.imshow('img1', img1) cv2.waitKey() cv2.destroyAllWindows()

结果:
Python学习|2021-9-21 opencv学习
文章图片

可见,我在蛇姐的图片上做了一个不透明的opencv的logo。
图像类型转换 BGR图像转RGB图像
BGR = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") RGB = cv2.cvtColor(BGR, cv2.COLOR_BGR2RGB)# BGR图像转RGB图像 cv2.imshow("BGR", BGR) cv2.imshow("RGB", RGB) cv2.waitKey() cv2.destroyAllWindows()

结果:

BGR图像转灰度图
BGR = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") GRAY = cv2.cvtColor(BGR, cv2.COLOR_BGR2GRAY)# BGR图像转灰度图 cv2.imshow("BGR", BGR) cv2.imshow("GRAY", GRAY) cv2.waitKey() cv2.destroyAllWindows()

结果:

灰度图转BGR图像
BGR = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") GRAY = cv2.cvtColor(BGR, cv2.COLOR_BGR2GRAY)# BGR图像转灰度图 BGR2 = cv2.cvtColor(GRAY, cv2.COLOR_GRAY2BGR)# 灰度图转BGR图像 cv2.imshow("GRAY", GRAY) cv2.imshow("BGR2", BGR2) cv2.waitKey() cv2.destroyAllWindows()

结果:

这在图像上可能看不出什么变化,但我们可以答应出图像的尺寸看看它们之间的区别。
print(GRAY.shape) print(BGR2.shape)

结果:
Python学习|2021-9-21 opencv学习
文章图片

可以看到,BGR图像的通道数为3。
灰度图转RGB图像
BGR = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png") GRAY = cv2.cvtColor(BGR, cv2.COLOR_BGR2GRAY)# BGR图像转灰度图 RGB2 = cv2.cvtColor(GRAY, cv2.COLOR_GRAY2RGB)# 灰度图转RGB图像 cv2.imshow("GRAY", GRAY) cv2.imshow("RGB2", RGB2) cv2.waitKey() cv2.destroyAllWindows()

结果:

与上面灰度图转BGR图像同理,从图像上看不出变化,但通道数为3。
Python学习|2021-9-21 opencv学习
文章图片

    推荐阅读