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的库函数。
先错误示范一下
- 首先我们在Anaconda Prompt窗口输入下列命令:
conda install opencv-python
【Python学习|2021-9-21 opencv学习】然后就会出现报错:
PackagesNotFoundError: The following packages are not available from current channels:
- python-opencv
- 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
looking for, navigate to https://anaconda.org and use the search bar at the top of the page.
这个大概就是现在opencv库不支持这样安装了,需要我们找到对应的版本进行安装
- 我们在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) # 保存图像。参数为要保存的完整文件名和读入的图像
这样就成功保存在桌面啦
文章图片
像素处理 读取像素
- 灰度图像 img[x, y] : 单通道图像
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png")
pixel = img[100, 100]
print(pixel)
结果:
文章图片
结果为什么会是三个数字呢?
opencv读取图像时会改变图片的格式。
那么如何读取图像时不改变图片格式呢?
读取图像时加入参数cv2.IMREAD_UNCHANGED
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png", cv2.IMREAD_UNCHANGED)
pixel = img[100, 100]
print(pixel)
结果:
文章图片
这样就是真正的单通道图片啦!
- 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)```
结果:
文章图片
即三通道的像素值分别为139, 160, 188
修改像素值
- 分通道处理
img[100, 100, 0] = 255
img[100, 100, 1] = 255
img[100, 100, 2] = 255
print(img[100, 100])
分别将三个通道的像素值都设置为255
结果:
文章图片
- 三通道同时处理
img[100, 100] = [0, 0, 0]
print(img[100, 100])
同时将三通道的像素值都设置为0
结果:
文章图片
3. 区域像素赋值
img[100:150, 100:150] = [255, 255, 255]
cv2.imshow("she", img)
cv2.waitKey()
cv2.destroyAllWindows()
显示结果:
区域内的所有通道像素值都是255,因此该区域为白色。
文章图片
使用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)
结果:
文章图片
同样可以获取到三通道各自的像素值
注意,彩色图不可以直接使用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))
结果:
文章图片
可以看到像素值改变了
访问图像属性 图像的形状
img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack.png")
print(img.shape)
结果:
文章图片
960行*640列, 三通道彩色图
图像的总像素数
print(img.size)
结果:
文章图片
960 * 640 = 1843200
图像的数据类型
print(img.dtype)
结果:
文章图片
关于数据类型,整型浮点型里面还有细分,这里就不多说了。
ROI(region of interest),感兴趣区域。 提取
cv2.imshow("face", img[100:400, 200:400])
cv2.waitKey()
cv2.destroyAllWindows()
结果:
文章图片
可以看到提取了脸部图像
复制 下面我们将脸部图像复制到图像的下方
img[500:800, 200:400] = img[100:400, 200:400]
cv2.imshow("demo", img)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
文章图片
拆分和合并通道 拆分通道(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
- 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)
结果:
文章图片
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()
结果:
文章图片
可以看到,两个图像按照一定的比例融合在一起。
按位运算 这包括按位 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()
结果:
文章图片
可见图片已经二值化,只有黑白两部分了。
mask_inv = cv2.bitwise_not(mask)# 非运算,黑白反转
cv2.imshow('mask_inv', mask_inv)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
文章图片
可见,与上图相比黑白发生反转。
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()
结果:
文章图片
res = cv2.add(img1_bg, img2_fg)
img1[:rows, :cols] = res
cv2.imshow('res', res)
cv2.imshow('img1', img1)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
文章图片
可见,我在蛇姐的图片上做了一个不透明的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)
结果:
文章图片
可以看到,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。
文章图片
推荐阅读
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 逻辑回归的理解与python示例
- 一起来学习C语言的字符串转换函数
- python自定义封装带颜色的logging模块
- 【Leetcode/Python】001-Two|【Leetcode/Python】001-Two Sum
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期