2021-9-21 opencv学习

在这里插入图片描述

关于Anaconda安装cv2

在学习opencv前,我们首先要安装opencv的库函数。

先错误示范一下

  1. 首先我们在Anaconda Prompt窗口输入下列命令:
conda install opencv-python

然后就会出现报错:
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 cv2

img = 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) # 保存图像。参数为要保存的完整文件名和读入的图像

这样就成功保存在桌面啦
在这里插入图片描述

像素处理

读取像素

  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)

结果:
在这里插入图片描述
结果为什么会是三个数字呢?
opencv读取图像时会改变图片的格式。

那么如何读取图像时不改变图片格式呢?
读取图像时加入参数cv2.IMREAD_UNCHANGED

img = cv2.imread("C:/Users/Zhang-Lei/Desktop/snack_gray.png", cv2.IMREAD_UNCHANGED)
pixel = img[100, 100]
print(pixel)

结果:
在这里插入图片描述
这样就是真正的单通道图片啦!

  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)```

结果:
在这里插入图片描述
即三通道的像素值分别为139, 160, 188

修改像素值

  1. 分通道处理
img[100, 100, 0] = 255
img[100, 100, 1] = 255
img[100, 100, 2] = 255
print(img[100, 100])

分别将三个通道的像素值都设置为255

结果:
在这里插入图片描述

  1. 三通道同时处理
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

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 plt

img = 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=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 np

x = 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。

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

giegie界清流

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值