opencv图片处理常见操作方法总结

OpenCV 图片处理常见操作方法总结

OpenCV (Open Source Computer Vision Library) 是计算机视觉领域最常用的开源库之一。以下是 OpenCV 图片处理的常见操作方法总结,包含代码示例和实际应用场景。

图片[1]_opencv图片处理常见操作方法总结_知途无界

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 图片处理的常见操作方法总结,涵盖了:

  1. 基础操作​:图像读取、显示、保存、属性获取
  2. 几何变换​:缩放、旋转、翻转
  3. 滤波增强​:平滑、锐化、形态学操作
  4. 阈值处理​:全局阈值、自适应阈值、Otsu方法
  5. 边缘检测​:Canny、Sobel、Laplacian
  6. 轮廓处理​:检测、绘制、属性计算、形状识别
  7. 特征检测​:Harris、Shi-Tomasi、SIFT、ORB
  8. 图像分割​:K-means、分水岭算法
  9. 绘制注释​:基本图形、文本添加
  10. 实用工具​:图像拼接、金字塔、直方图

这些方法覆盖了计算机视觉中最常用的图像处理技术,可以根据具体应用场景选择合适的方法进行图像分析和处理。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞8 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容