OpenCV基础的图像操作
1.读取图像
cv2.imread(path,[读取方式])
参数:
-
path:要读取的图像路径
-
读取方式的标志(彩色-默认,灰色等等),可以在读取图片时进行操作,例如将图片转化为灰度图像等
2.显示图像
cv2.imshow(name,image_name)
参数:
- name:显示图像的窗口名称,以字符串类型表示
- image_name:要加载的图像
注意:在调用显示图像的API后,要调用cv2.waitKey(0)给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来
3.保存图像
cv2.imwrite(path,image_name)
参数:
- path:文件名,要保存在哪里
- image_name:要保存的图像
import cv2
# 读取图像
im = cv2.imread('./my_images/1.png')
# 显示图像
cv2.imshow("img", im)
# 保存图像
# 将图像转化为灰度图像
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
cv2.imwrite("./my_images/2.png", im)
cv2.waitKey(0)
绘制几何图形
1.绘制直线
cv2.line(img,start,end,color,thickness)
参数:
- img:要绘制直线的图像
- Start,end: 直线的起点和终点
- color: 线条的颜色
- Thickness: 线条宽度
2.绘制圆形
cv.circle(img,centerpoint, r, color, thickness)
参数:
- img:要绘制圆形的图像
- centerpoint, r: 圆心和半径
- color: 线条的颜色
- thickness: 线条宽度,为-1时生成闭合图案并填充颜色
3.绘制矩形
cv.rectangle(img,leftupper,rightdown,color,thickness)
参数:
- img:要绘制矩形的图像
- Leftupper, rightdown: 矩形的左上角和右下角坐标
- color: 线条的颜色
- Thickness: 线条宽度
4.向图像中添加文字
cv.putText(img,text,org, fontFace, Fontscale ,color,thickness,cv2.LINE_AA)
参数:
-
img: 图像
-
text:要写入的文本数据
-
org:文本的放置位置
-
fontFace:字体样式
-
Fontscale :字体大小
-
color:字体颜色
-
thickness字体线条宽度
-
cv2.LINE_AA
最后一个参数
cv2.LINE_AA
表示使用反走样(Anti-Aliasing)技术来绘制文本边框。不填该参数时,默认使用的是cv2.LINE_8
import cv2
# 绘制直线
im = cv2.imread("./my_images/1.png")
# print(im.shape)
cv2.line(im, (100, 100), (900, 100), (0, 0, 255), 2)
# 绘制圆形
cv2.circle(im, (450, 500), 100, (255, 0, 0), 1)
# 绘制矩形
cv2.rectangle(im, (300, 300), (600, 600), (0, 255, 0), 2)
# 向图像中添加文字
cv2.putText(im, "yahu!!!", (100, 150), cv2.FONT_ITALIC, 2, (255, 0, 0))
# 修改图像中的某一个像素点
im[50, 50] = [0, 0, 255]
cv2.imshow("img", im)
cv2.waitKey(0)
摄像头操作
注意:在使用完摄像头之后要记住释放资源关闭摄像头
import cv2
"""
cap = cv2.VideoCapture(path)# path视频文件,当参数设置为0时,表示从默认摄像头获取视频
ret, frame = cap.read()# 返回一个布尔值和一帧图像
"""
cap = cv2.VideoCapture(0)
while True:
# 获取一帧图像
ret, frame = cap.read()
if ret is False or cv2.waitKey(1) == ord('q'):
break
# 对图像进行灰度化处理
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 采用高斯加权求和进行自适应二值化
frame = cv2.adaptiveThreshold(frame, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 5)
cv2.imshow('frame', frame)
# 释放摄像头资源并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
计算机眼中的图像
1.像素
像素是图像的基本单元,每个像素存储着图像的颜色、亮度和其他特征。一系列像素组合到一起就形成了完整的图像,在计算机中,图像以像素的形式存在并采用二进制格式进行存储。根据图像的颜色不同,每个像素可以用不同的二进制数表示。
日常生活中常见的图像是RGB三原色图。RGB图上的每个点都是由红(R)、绿(G)、蓝(B)三个颜色按照一定比例混合而成的,几乎所有颜色都可以通过这三种颜色按照不同比例调配而成。在计算机中,RGB三种颜色被称为RGB三通道,根据这三个通道存储的像素值,来对应不同的颜色。
2.图像
计算机采用0/1编码的系统,数字图像也是利用0/1来记录信息,我们平常接触的图像都是8位数图像,包含0~255灰度,其中0,代表最黑,1,表示最白。
常用的图像:
- 二值图像:图像中的颜色只有两种值可取
- 灰度图:单通道图
- 彩色图:R,G,B三通道图
图像灰度化方法
1. 最大值法
对于彩色图像的每个像素,它会从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值。
2. 平均值法
对于彩色图像的每个像素,它会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值。
3. 加权均值法
对于彩色图像的每个像素,它会按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值。
import cv2
import numpy as np
# 最大值法
im = cv2.imread("./my_images/1.png")
im_gray = np.zeros((im.shape[0], im.shape[1]), dtype=np.uint8)
for row in range(im.shape[0]):
for col in range(im.shape[1]):
im_gray[row, col] = max(im[row, col][0], im[row, col][1], im[row, col][2])
cv2.imshow("im_gray", im_gray)
cv2.waitKey(0)
# 平均值法
im = cv2.imread("./my_images/1.png")
im_gray = np.zeros((im.shape[0], im.shape[1]), dtype=np.uint8)
for row in range(im.shape[0]):
for col in range(im.shape[1]):
im_gray[row, col] = (int(im[row, col][0]) + int(im[row, col][1]) + int(im[row, col][2]))/3
cv2.imshow("im_gray", im_gray)
cv2.waitKey(0)
# 加权均值法
im = cv2.imread("./my_images/1.png")
im_gray = np.zeros((im.shape[0], im.shape[1]), dtype=np.uint8)
for row in range(im.shape[0]):
for col in range(im.shape[1]):
im_gray[row, col] = int(im[row, col][0]*0.114) + int(im[row, col][1]*0.587) + int(im[row, col][2]*0.299)
cv2.imshow("im_gray", im_gray)
cv2.waitKey(0)
二值化方法
1. 阈值法(THRESH_BINARY)
阈值法就是通过设置一个阈值,将灰度图中的每一个像素值与该阈值进行比较,小于等于阈值的像素就被设置为0(黑),大于阈值的像素就被设置为maxval。
2. 反阈值法(THRESH_BINARY_INV)
顾名思义,就是与阈值法相反。反阈值法是当灰度图的像素值大于阈值时,该像素值将会变成0(黑),当灰度图的像素值小于等于阈值时,该像素值将会变成maxval。
3. 截断阈值法(THRESH_TRUNC)
截断阈值法,指将灰度图中的所有像素与阈值进行比较,像素值大于阈值的部分将会被修改为阈值,小于等于阈值的部分不变。
4. 低阈值零处理(THRESH_TOZERO)
低阈值零处理,像素值小于等于阈值的部分被置为0,大于阈值的部分不变。
5. 超阈值零处理(THRESH_TOZERO_INV)
超阈值零处理将灰度图中的每个像素与阈值进行比较,像素值大于阈值的部分置为0,像素值小于等于阈值的部分不变。
import cv2
# 读入图片转化为灰度图像
im = cv2.imread("./my_images/1.png", cv2.IMREAD_GRAYSCALE)
# 阈值法,阈值为127,大于阈值设置为255,小于设置为0
_, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY)
cv2.imshow("im", im)
cv2.waitKey(0)
# 反阈值法,阈值为127,大于阈值设置为0,小于设置为255
_, im = cv2.threshold(im, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("im", im)
cv2.waitKey(0)
# 截断阈值法,大于阈值的部分将会被修改为阈值,小于等于阈值的部分不变
_, im = cv2.threshold(im, 127, 255, cv2.THRESH_TRUNC)
cv2.imshow("im", im)
cv2.waitKey(0)
# 低阈值零处理,像素值小于等于阈值的部分被置为0,大于阈值的部分不变
_, im = cv2.threshold(im, 127, 255, cv2.THRESH_TOZERO)
cv2.imshow("im", im)
cv2.waitKey(0)
# 超阈值零处理,像素值大于等于阈值的部分被置为0,小于阈值的部分不变
_, im = cv2.threshold(im, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow("im", im)
cv2.waitKey(0)
6.OTSU阈值法(后续补充)
自适应二值化方法
与二值化算法相比,自适应二值化更加适合用在明暗分布不均的图片,图片上的每一小部分都要使用不同的阈值进行二值化处理
cv2.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)
参数:
- maxval:最大阈值,一般为255
- adaptiveMethod:小区域阈值的计算方式:
- ADAPTIVE_THRESH_MEAN_C:小区域内取均值
- ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核
- thresholdType:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法
- blockSize:卷积核,选取的小区域的面积,如7就是7*7的小块。
- c:最终阈值等于小区域计算出的阈值再减去此值
1.取均值
注意:如果处于边缘地区就会对边界进行填充,填充值就是边界的像素点。我们所用到的不断滑动的小区域被称之为核,比如3*3的小区域叫做3*3的核,并且核的大小都是奇数个,也就是3*3、5*5、7*7等。
2.加权求和
对小区域内的像素进行加权求和得到新的阈值,其权重值来自于高斯分布。
高斯分布,通过概率密度函数来定义高斯分布,一维高斯概率分布函数为:
p
(
y
)
=
1
σ
2
π
e
−
(
y
−
μ
)
2
2
σ
2
p(y)={\frac{1}{\sigma{\sqrt{2\pi}}}}e^{{\frac{-(y-\mu)^{2}}{2\sigma^{2}}}}
p(y)=σ2π1e2σ2−(y−μ)2
此时我们拓展到二维图像,一般情况下我们使x轴和y轴的相等并且,此时我们可以得到二维高斯函数的表达式为:
g
(
x
,
y
)
=
1
2
π
σ
2
e
−
(
x
2
+
y
2
)
2
σ
2
g(x,y)=\frac{1}{2\pi\sigma ^{2}}e^{-\frac{(x^{2}+y^{2})}{2\sigma^{2}}}
g(x,y)=2πσ21e−2σ2(x2+y2)
要产生一个3*3的高斯权重核,以核的中心位置为坐标原点进行取样,其周围的坐标如下图所示(x轴水平向右,y轴竖直向上)
kernel尺寸 | 核值 |
---|---|
1 | [1] |
3 | [0.25, 0.5, 0.25] |
5 | [0.0625, 0.25, 0.375, 0.25, 0.0625] |
7 | [0.03125, 0.109375, 0.21875, 0.28125, 0.21875, 0.109375, 0.03125] |
当核的大小为3x3时,我们使用kernel尺寸为3的核值乘以它对应的矩阵的转置得到一个方阵,最终的到kernel高斯核,再相应的对应到每个像素点进行加权求和即可得到中心点的阈值
注:
-
在opencv里,当kernel(小区域)的尺寸为1、3、5、7并且用户没有设置sigma的时候(sigma <= 0),核值就会取固定的系数,这是一种默认的值是高斯函数的近似。
-
当kernels尺寸超过7的时候,如果sigma设置合法(用户设置了sigma),则按照高斯公式计算.当sigma不合法(用户没有设置sigma),则按照如下公式计算sigma的值:
σ = 0.3 ∗ ( ( k s i z e − 1 ) ∗ 0.5 − 1 ) + 0.8 \sigma=0.3*\big((k s i z e-1)*0.5-1\big)+0.8 σ=0.3∗((ksize−1)∗0.5−1)+0.8
import cv2
# 读入图片转化为灰度图像
im = cv2.imread("./my_images/1.png", cv2.IMREAD_GRAYSCALE)
cv2.imshow("im", im)
cv2.waitKey(0)
# 取均值法
im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 5)
cv2.imshow("im", im)
cv2.waitKey(0)
# 加权求和法
im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 5)
cv2.imshow("im", im)
cv2.waitKey(0)
读入图片转化为灰度图像
im = cv2.imread(“./my_images/1.png”, cv2.IMREAD_GRAYSCALE)
cv2.imshow(“im”, im)
cv2.waitKey(0)
取均值法
im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 5)
cv2.imshow(“im”, im)
cv2.waitKey(0)
加权求和法
im = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 5)
cv2.imshow(“im”, im)
cv2.waitKey(0)