OpenCV 图片处理常见操作方法总结
OpenCV (Open Source Computer Vision Library) 是计算机视觉领域最常用的开源库之一。以下是 OpenCV 图片处理的常见操作方法总结,包含代码示例和实际应用场景。
![图片[1]_opencv图片处理常见操作方法总结_知途无界](https://zhituwujie.com/wp-content/uploads/2026/01/d2b5ca33bd20260110115237-1024x532.png)
1. 环境准备与基础操作
安装 OpenCV
pip install opencv-python
pip install opencv-contrib-python # 包含额外模块
基础导入和图像读取
import cv2
import numpy as np
# 读取图像
img = cv2.imread('image.jpg')
# 检查图像是否加载成功
if img is None:
print("图像加载失败")
else:
print(f"图像尺寸: {img.shape}") # (高度, 宽度, 通道数)
print(f"图像数据类型: {img.dtype}")
# 显示图像
cv2.imshow('Image', img)
cv2.waitKey(0) # 等待按键
cv2.destroyAllWindows() # 关闭所有窗口
# 保存图像
cv2.imwrite('output.jpg', img)
2. 图像基本属性与变换
获取和修改图像属性
# 获取图像属性
height, width, channels = img.shape
print(f"宽度: {width}, 高度: {height}, 通道数: {channels}")
# 获取图像数据类型和大小
print(f"数据类型: {img.dtype}")
print(f"图像大小: {img.size} 像素")
# 转换颜色空间
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # BGR转灰度
rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR转RGB
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR转HSV
图像缩放
# 方法1: resize()
resized_img = cv2.resize(img, (new_width, new_height))
# 方法2: 按比例缩放
scale_factor = 0.5
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)
resized_img = cv2.resize(img, (new_width, new_height))
# 不同的插值方法
resized_nearest = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_NEAREST)
resized_linear = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_LINEAR)
resized_cubic = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_CUBIC)
图像旋转
# 获取图像中心
center = (width // 2, height // 2)
# 获取旋转矩阵 (角度, 缩放比例)
rotation_matrix = cv2.getRotationMatrix2D(center, angle=45, scale=1.0)
# 应用仿射变换
rotated_img = cv2.warpAffine(img, rotation_matrix, (width, height))
# 旋转并扩展画布以避免裁剪
def rotate_image(image, angle):
height, width = image.shape[:2]
center = (width // 2, height // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
# 计算新边界尺寸
cos_val = abs(rotation_matrix[0, 0])
sin_val = abs(rotation_matrix[0, 1])
new_width = int((height * sin_val) + (width * cos_val))
new_height = int((height * cos_val) + (width * sin_val))
# 调整旋转矩阵
rotation_matrix[0, 2] += (new_width / 2) - center[0]
rotation_matrix[1, 2] += (new_height / 2) - center[1]
rotated_img = cv2.warpAffine(image, rotation_matrix, (new_width, new_height))
return rotated_img
图像翻转
# 水平翻转
flipped_h = cv2.flip(img, 1)
# 垂直翻转
flipped_v = cv2.flip(img, 0)
# 水平和垂直翻转
flipped_hv = cv2.flip(img, -1)
3. 图像滤波与增强
平滑滤波
# 均值滤波
blurred_mean = cv2.blur(img, (5, 5)) # 5x5卷积核
# 高斯滤波
blurred_gaussian = cv2.GaussianBlur(img, (5, 5), 0) # sigmaX=0自动计算
# 中值滤波 (有效去除椒盐噪声)
blurred_median = cv2.medianBlur(img, 5) # 孔径大小=5
# 双边滤波 (保持边缘的平滑)
blurred_bilateral = cv2.bilateralFilter(img, 9, 75, 75)
锐化滤波
# 使用拉普拉斯算子锐化
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
sharpened = cv2.filter2D(img, -1, kernel)
# 自定义锐化核
sharpen_kernel = np.array([[0, -1, 0],
[-1, 5, -1],
[0, -1, 0]])
sharpened_custom = cv2.filter2D(img, -1, sharpen_kernel)
形态学操作
# 定义结构元素
kernel = np.ones((5, 5), np.uint8)
# 腐蚀 (缩小白色区域)
eroded = cv2.erode(img, kernel, iterations=1)
# 膨胀 (扩大白色区域)
dilated = cv2.dilate(img, kernel, iterations=1)
# 开运算 (先腐蚀后膨胀,去除小物体)
opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 闭运算 (先膨胀后腐蚀,填充小孔洞)
closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
# 形态学梯度 (膨胀图 - 腐蚀图,得到边缘)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
4. 图像阈值处理
基本阈值处理
# 全局阈值
ret, thresh_binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
ret, thresh_binary_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh_trunc = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh_tozero = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh_tozero_inv = cv2.threshold(gray_img, 127, 255, cv2.THRESH_TOZERO_INV)
# 自适应阈值 (适合光照不均匀的图像)
adaptive_thresh = cv2.adaptiveThreshold(
gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
)
# Otsu's 二值化 (自动确定最佳阈值)
ret, otsu_thresh = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
大津阈值法示例
def otsu_threshold(image):
# 计算直方图
hist = cv2.calcHist([image], [0], None, [256], [0, 256])
hist_norm = hist.ravel() / hist.sum()
# 计算累积和
cumsum = np.cumsum(hist_norm)
cumvar = np.cumsum(hist_norm * np.arange(256))
# 计算类间方差
global_mean = np.sum(np.arange(256) * hist_norm)
between_var = ((global_mean * cumsum - cumvar) ** 2) / (cumsum * (1 - cumsum) + 1e-7)
# 找到最大类间方差对应的阈值
optimal_threshold = np.argmax(between_var)
return optimal_threshold
otsu_thresh_value = otsu_threshold(gray_img)
print(f"Otsu最佳阈值: {otsu_thresh_value}")
5. 边缘检测
Canny 边缘检测
# 高斯滤波去噪
blurred = cv2.GaussianBlur(gray_img, (5, 5), 0)
# Canny边缘检测
edges = cv2.Canny(blurred, threshold1=50, threshold2=150)
# 可调参数的Canny
def auto_canny(image, sigma=0.33):
median = np.median(image)
lower = int(max(0, (1.0 - sigma) * median))
upper = int(min(255, (1.0 + sigma) * median))
edged = cv2.Canny(image, lower, upper)
return edged
auto_edges = auto_canny(blurred)
Sobel 和 Laplacian 边缘检测
# Sobel 边缘检测
sobel_x = cv2.Sobel(gray_img, cv2.CV_64F, 1, 0, ksize=3) # X方向
sobel_y = cv2.Sobel(gray_img, cv2.CV_64F, 0, 1, ksize=3) # Y方向
sobel_magnitude = np.sqrt(sobel_x**2 + sobel_y**2)
sobel_magnitude = np.uint8(sobel_magnitude / sobel_magnitude.max() * 255)
# Laplacian 边缘检测
laplacian = cv2.Laplacian(gray_img, cv2.CV_64F)
laplacian_abs = np.uint8(np.absolute(laplacian))
6. 轮廓检测与绘制
轮廓检测
# 二值化图像
ret, binary = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
# 查找轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 轮廓检索模式:
# cv2.RETR_EXTERNAL: 只检测外轮廓
# cv2.RETR_LIST: 检测所有轮廓,不建立层次关系
# cv2.RETR_TREE: 检测所有轮廓,建立完整的层次关系
# 轮廓近似方法:
# cv2.CHAIN_APPROX_NONE: 存储所有轮廓点
# cv2.CHAIN_APPROX_SIMPLE: 压缩水平、垂直和对角线段,只保留端点
轮廓绘制与属性计算
# 创建空白图像用于绘制轮廓
contour_img = np.zeros_like(img)
# 绘制所有轮廓
cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2)
# 绘制特定轮廓
cv2.drawContours(contour_img, contours, 0, (0, 0, 255), 3)
# 计算轮廓属性
for i, contour in enumerate(contours):
# 面积
area = cv2.contourArea(contour)
# 周长
perimeter = cv2.arcLength(contour, True)
# 外接矩形
x, y, w, h = cv2.boundingRect(contour)
# 最小外接矩形
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
# 凸包
hull = cv2.convexHull(contour)
# 近似多边形
epsilon = 0.02 * perimeter
approx = cv2.approxPolyDP(contour, epsilon, True)
print(f"轮廓 {i}: 面积={area:.2f}, 周长={perimeter:.2f}, 顶点数={len(approx)}")
形状识别示例
def detect_shapes(image):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
shape_names = []
for contour in contours:
# 计算轮廓近似
epsilon = 0.04 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
# 根据顶点数判断形状
vertices = len(approx)
if vertices == 3:
shape = "三角形"
elif vertices == 4:
# 检查是否是正方形
x, y, w, h = cv2.boundingRect(approx)
aspect_ratio = float(w) / h
if 0.95 <= aspect_ratio <= 1.05:
shape = "正方形"
else:
shape = "矩形"
elif vertices == 5:
shape = "五边形"
elif vertices == 6:
shape = "六边形"
else:
shape = "圆形"
shape_names.append(shape)
# 在图像上标注形状
cv2.drawContours(image, [approx], -1, (0, 255, 0), 2)
cv2.putText(image, shape, (approx[0][0][0], approx[0][0][1]),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
return image, shape_names
7. 图像特征检测
Harris 角点检测
# Harris 角点检测
gray = np.float32(gray_img)
harris_corners = cv2.cornerHarris(gray, blockSize=2, ksize=3, k=0.04)
# 膨胀角点以增强显示
harris_corners = cv2.dilate(harris_corners, None)
# 标记角点 (阈值设为角点响应的0.01倍)
img[harris_corners > 0.01 * harris_corners.max()] = [0, 0, 255]
Shi-Tomasi 角点检测
# Shi-Tomasi 角点检测
corners = cv2.goodFeaturesToTrack(gray_img, maxCorners=100, qualityLevel=0.01, minDistance=10)
if corners is not None:
corners = np.int0(corners)
for corner in corners:
x, y = corner.ravel()
cv2.circle(img, (x, y), 3, (0, 255, 0), -1)
SIFT 特征检测 (需要 opencv-contrib-python)
# SIFT 特征检测和描述
sift = cv2.SIFT_create()
keypoints, descriptors = sift.detectAndCompute(gray_img, None)
# 绘制关键点
img_sift = cv2.drawKeypoints(img, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
ORB 特征检测 (免费替代方案)
# ORB 特征检测
orb = cv2.ORB_create(nfeatures=1000)
keypoints, descriptors = orb.detectAndCompute(gray_img, None)
# 绘制关键点
img_orb = cv2.drawKeypoints(img, keypoints, None, color=(0, 255, 0), flags=0)
8. 图像分割
K-means 聚类分割
def kmeans_segmentation(image, k=4):
# 将图像转换为二维数组
data = image.reshape((-1, 3))
data = np.float32(data)
# 定义K-means参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 20, 1.0)
_, labels, centers = cv2.kmeans(data, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
# 将中心转换为uint8
centers = np.uint8(centers)
# 映射每个像素到对应的中心
segmented_data = centers[labels.flatten()]
segmented_image = segmented_data.reshape(image.shape)
return segmented_image
# 使用示例
segmented = kmeans_segmentation(img, k=4)
分水岭算法分割
def watershed_segmentation(image):
# 转换为灰度图并应用阈值
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 去除噪声
kernel = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)
# 确定背景区域
sure_bg = cv2.dilate(opening, kernel, iterations=3)
# 确定前景区域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
# 找到未知区域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)
# 标记连通组件
ret, markers = cv2.connectedComponents(sure_fg)
# 为所有标记加1,使背景不为0
markers = markers + 1
# 标记未知区域为0
markers[unknown == 255] = 0
# 应用分水岭算法
markers = cv2.watershed(image, markers)
image[markers == -1] = [255, 0, 0] # 边界标记为红色
return image
9. 图像绘制与注释
基本图形绘制
# 创建空白图像
canvas = np.ones((400, 600, 3), dtype=np.uint8) * 255
# 绘制直线
cv2.line(canvas, (0, 0), (200, 100), (255, 0, 0), 2) # 蓝色直线
# 绘制矩形
cv2.rectangle(canvas, (50, 50), (150, 150), (0, 255, 0), 2) # 绿色矩形
cv2.rectangle(canvas, (200, 50), (300, 150), (0, 0, 255), -1) # 红色实心矩形
# 绘制圆形
cv2.circle(canvas, (400, 100), 50, (255, 255, 0), 2) # 青色圆
cv2.circle(canvas, (500, 100), 30, (255, 0, 255), -1) # 紫色实心圆
# 绘制椭圆
cv2.ellipse(canvas, (100, 300), (50, 30), 0, 0, 360, (0, 255, 255), 2)
# 绘制多边形
pts = np.array([[200, 250], [250, 200], [350, 200], [400, 250], [350, 300], [250, 300]], np.int32)
pts = pts.reshape((-1, 1, 2))
cv2.polylines(canvas, [pts], True, (128, 0, 128), 2)
文本添加
# 添加文本
cv2.putText(canvas, "Hello OpenCV!", (50, 380),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
# 不同字体
fonts = [
cv2.FONT_HERSHEY_SIMPLEX,
cv2.FONT_HERSHEY_PLAIN,
cv2.FONT_HERSHEY_DUPLEX,
cv2.FONT_HERSHEY_COMPLEX,
cv2.FONT_HERSHEY_TRIPLEX,
cv2.FONT_HERSHEY_COMPLEX_SMALL,
cv2.FONT_HERSHEY_SCRIPT_SIMPLEX,
cv2.FONT_HERSHEY_SCRIPT_COMPLEX
]
for i, font in enumerate(fonts):
cv2.putText(canvas, f"Font {i}", (50 + i*70, 420),
font, 0.5, (255, 0, 0), 1)
10. 实用工具函数
图像拼接
def stitch_images(images):
"""
简单图像拼接 (需要安装 opencv-contrib-python)
"""
stitcher = cv2.Stitcher.create()
status, stitched = stitcher.stitch(images)
if status == cv2.Stitcher_OK:
return stitched
else:
print("图像拼接失败")
return None
# 使用示例
# images = [cv2.imread('img1.jpg'), cv2.imread('img2.jpg'), cv2.imread('img3.jpg')]
# result = stitch_images(images)
图像金字塔
# 高斯金字塔
smaller = cv2.pyrDown(img) # 下采样
larger = cv2.pyrUp(img) # 上采样
# 拉普拉斯金字塔
def laplacian_pyramid(image, levels=3):
pyramid = []
current = image.copy()
for i in range(levels):
smaller = cv2.pyrDown(current)
larger = cv2.pyrUp(smaller, dstsize=(current.shape[1], current.shape[0]))
laplacian = cv2.subtract(current, larger)
pyramid.append(laplacian)
current = smaller
pyramid.append(current) # 最后一层是高斯金字塔的最小层
return pyramid
图像直方图
# 计算直方图
hist_b = cv2.calcHist([img], [0], None, [256], [0, 256]) # 蓝色通道
hist_g = cv2.calcHist([img], [1], None, [256], [0, 256]) # 绿色通道
hist_r = cv2.calcHist([img], [2], None, [256], [0, 256]) # 红色通道
# 绘制直方图
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 4))
plt.subplot(1, 3, 1)
plt.plot(hist_b, color='b')
plt.title('Blue Channel Histogram')
plt.subplot(1, 3, 2)
plt.plot(hist_g, color='g')
plt.title('Green Channel Histogram')
plt.subplot(1, 3, 3)
plt.plot(hist_r, color='r')
plt.title('Red Channel Histogram')
plt.tight_layout()
plt.show()
总结
以上是 OpenCV 图片处理的常见操作方法总结,涵盖了:
- 基础操作:图像读取、显示、保存、属性获取
- 几何变换:缩放、旋转、翻转
- 滤波增强:平滑、锐化、形态学操作
- 阈值处理:全局阈值、自适应阈值、Otsu方法
- 边缘检测:Canny、Sobel、Laplacian
- 轮廓处理:检测、绘制、属性计算、形状识别
- 特征检测:Harris、Shi-Tomasi、SIFT、ORB
- 图像分割:K-means、分水岭算法
- 绘制注释:基本图形、文本添加
- 实用工具:图像拼接、金字塔、直方图
这些方法覆盖了计算机视觉中最常用的图像处理技术,可以根据具体应用场景选择合适的方法进行图像分析和处理。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
























暂无评论内容