参考:
GitHub - kongfanhe/opencv_tutorial
OpenCV Python 图像处理 30分钟 入门课程_哔哩哔哩_bilibili
OpenCV的基本示例
# 基本IO
import cv2
# 读取版本号
print(cv2.getVersionString())
# 读取图片
image = cv2.imread("opencv_logo.jpg")
# 打印图片的形状(高度,宽度,通道数)
print(image.shape)
cv2.imshow("image", image)
cv2.waitKey() # 让窗口暂停
图像的彩色通道BGR
# 图像的颜色
import cv2
image = cv2.imread("opencv_logo.jpg")
# 颜色通道顺序:BGR
cv2.imshow("blue", image[:, :, 0])
cv2.imshow("green", image[:, :, 1])
cv2.imshow("red", image[:, :, 2])
# 彩色图片灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("gray", gray)
cv2.waitKey()
图像的裁剪
# 图像裁剪操作
import cv2
image = cv2.imread("opencv_logo.jpg")
crop = image[10:170, 40:200]
cv2.imshow("crop", crop)
cv2.waitKey()
绘制直线、矩形、圆形
# 实现绘图功能
import cv2
import numpy as np
# 创建黑色画布
image = np.zeros([300, 300, 3], dtype=np.uint8)
# 绘制线段(对象, 起点, 终点, 颜色, 粗细)
cv2.line(image, (100, 200), (250, 250), (255, 0, 0), 2)
# 绘制矩形(~,起点, 对角点, 颜色, 粗细)
cv2.rectangle(image, (30, 100), (60, 150), (0, 255, 0), 2)
# 绘制圆形(~,圆心, 半径, 颜色, 粗细)
cv2.circle(image, (150, 100), 20, (0, 0, 255), 3)
# 绘制字符串(~, 内容, 坐标, 字体格式序号, 缩放系数, 颜色, 粗细, 线条类型序号)
cv2.putText(image, "hello", (100, 50), 0, 1, (255, 255, 255), 2, 1)
cv2.imshow("image", image)
cv2.waitKey()
均值滤波处理图像噪点
# 图形的滤波
import cv2
image = cv2.imread("plane.jpg")
# 使用高斯滤波器
gauss = cv2.GaussianBlur(image, (5, 5), 0)
# 使用均值滤波器
median = cv2.medianBlur(image, 5)
cv2.imshow("image", image)
cv2.imshow("gauss", gauss)
cv2.imshow("median", median)
cv2.waitKey()
'''
高斯滤波(Gaussian Blur)和均值滤波(Mean Blur)都是图像处理中常用的平滑技术,它们用于减少图像噪声、模糊图像边缘或细节,以及进行图像预处理。
选择使用哪种滤波方法取决于具体的应用场景和需求。
均值滤波:
简单易实现,对所有像素的邻域内的像素值求平均。
对于去除随机噪声(如椒盐噪声)效果较好。
对图像的边缘和细节的模糊程度较高,可能导致图像质量下降。
高斯滤波:
使用高斯分布作为权重,对邻域内的像素进行加权平均。
对图像的边缘和细节的模糊程度较低,通常能更好地保留图像的结构信息。
实现相对复杂,需要计算高斯核的权重。
在实际应用中,高斯滤波通常更受欢迎,因为它在平滑图像的同时能更好地保留图像的边缘和细节。
然而,如果处理速度是一个关键因素,均值滤波由于其简单性可能会更快。此外,对于某些特定的噪声类型,均值滤波可能更有效。
在决定使用哪种滤波方法时,可以考虑以下因素:
图像内容:如果图像中包含重要的边缘信息,高斯滤波可能更合适。
噪声类型:如果主要是随机噪声,均值滤波可能更有效。
实现复杂度:如果需要快速实现,均值滤波可能更简单。
性能要求:如果对图像质量有较高要求,高斯滤波通常能提供更好的结果。
在某些情况下,也可以结合使用这两种滤波方法,或者尝试其他类型的滤波器,如双边滤波(Bilateral Filter),它在平滑图像的同时能更好地保留边缘。
'''
图像特征点的提取
# 图片特征的提取
import cv2
image = cv2.imread("opencv_logo.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 图片先灰度化
# 获取特征点 (对象, 最多的点数, 质量优度水平, 特征点之间的最小距离)
corners = cv2.goodFeaturesToTrack(gray, 500, 0.1, 10)
# 标记出每个点
for corner in corners:
x, y = corner.ravel()
cv2.circle(image, (int(x), int(y)), 3, (255, 0, 255), -1)
cv2.imshow("corners", image)
cv2.waitKey()
# 可以发现,特征点主要都在图片的转角处
模板匹配扑克牌上的菱形
# 图片的模板匹配(以匹配扑克牌上的菱形为例)
import cv2
import numpy as np
image = cv2.imread("poker.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 选取匹配模板
template = gray[75:105, 235:265]
# 使用标准相关匹配算法——将待检测对象和模板都标准化再来计算匹配度
match = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
locations = np.where(match >= 0.9) # 找出匹配系数大于0.9的匹配点
w, h = template.shape[0:2]
for p in zip(*locations[::-1]): # 循环遍历每一个匹配点并画出矩形框标记
x1, y1 = p[0], p[1]
x2, y2 = x1 + w, y1 + h
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("image", image)
cv2.waitKey()
图像的梯度算法与边缘检测
# 图像的梯度(明暗变化)
import cv2
gray = cv2.imread("opencv_logo.jpg", cv2.IMREAD_GRAYSCALE) # 直接读取为灰度图
# 使用拉普拉斯算子(检测边缘——梯度剧烈变化处)
laplacian = cv2.Laplacian(gray, cv2.CV_64F)
# canny边缘检测(定义边缘为梯度区间)
# 梯度大于200 -> 变化足够强烈,确定是边缘
# 梯度小于100 -> 变化较为平缓,确定非边缘
# 梯度介于二者之间 -> 待定,看其是否与已知的边缘像素相邻
canny = cv2.Canny(gray, 100, 200)
cv2.imshow("gray", gray)
cv2.imshow("laplacian", laplacian)
cv2.imshow("canny", canny)
cv2.waitKey()
图像的二值化
# 图片的阈值算法(二值化,将连续的灰度范围切割为白+黑)
import cv2
# 图片灰度二值化
gray = cv2.imread("bookpage.jpg", cv2.IMREAD_GRAYSCALE)
ret, binary = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)
# 图片自适应二值化(划分区块二值化,效果更好)
binary_adaptive = cv2.adaptiveThreshold(
gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 115, 1)
# 大津算法(基于图片灰度聚类分析,自定义阈值)
ret1, binary_otsu = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow("gray", gray)
cv2.imshow("binary", binary)
cv2.imshow("adaptive", binary_adaptive)
cv2.imshow("otsu", binary_otsu)
cv2.waitKey()
# ret/ret1是一个浮点数,表示图像中像素值的阈值
print(ret)
print(ret1)
图像形态学之腐蚀和膨胀
# 图像的形态学算法(腐蚀和膨胀)
import cv2
import numpy as np
# 在腐蚀和膨胀之前需要先将图片二值化
gray = cv2.imread("opencv_logo.jpg", cv2.IMREAD_GRAYSCALE)
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV) # 使用反向阈值——背景白色,图案黑色
kernel = np.ones((5, 5), np.uint8) # 操作需要用到的kernel
# 腐蚀和膨胀操作
erosion = cv2.erode(binary, kernel)
dilation = cv2.dilate(binary, kernel)
cv2.imshow("binary", binary)
cv2.imshow("erosion", erosion)
cv2.imshow("dilation", dilation)
cv2.waitKey()
调用电脑摄像头
# opencv调用电脑中的摄像头
import cv2
# 获取摄像头设备的指针(设备管理器 -> 照相机)
capture = cv2.VideoCapture(0)
ret = True
# 摄像头的读取是连续不断的,需要循环读取
while ret:
ret, frame = capture.read()
'''
ret:这是一个布尔值,表示读取操作是否成功。
如果 ret 为 True,表示成功读取了一帧图像;如果为 False,则表示读取失败,可能是因为视频流结束或者其他错误。
在处理视频流时,这个返回值通常用于控制循环,直到视频流结束。
frame:这是一个NumPy数组,代表了从视频捕获对象读取的当前帧。
这个数组通常是一个三维的,其形状为 (高度, 宽度, 通道数),其中通道数可以是1(灰度图像)或3(彩色图像,分别对应红、绿、蓝通道)。
'''
cv2.imshow("camera", frame)
key = cv2.waitKey(1) # 等待键盘输入1ms
if key != -1: # 按任意键跳出循环
break
capture.release() # 释放指针