OpenCV图片操作100例:从入门到精通指南(4)

发布于:2025-07-11 ⋅ 阅读:(19) ⋅ 点赞:(0)

OpenCV实战进阶:解锁计算机视觉高级技能

这些示例融合了深度学习、三维视觉和工业级应用,助力你成为OpenCV专家

六、专业级视觉处理

71. 图像配准(高精度对齐)

# 特征提取
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

# 特征匹配
bf = cv2.BFMatcher()
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)[:50]

# 计算变换矩阵
src_pts = np.float32([kp1[m.queryIdx].pt for m in matches])
dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches])
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

# 应用变换
registered = cv2.warpPerspective(img1, M, (img2.shape[1], img2.shape[0]))

应用:医学影像序列对齐

72. 去雾算法(暗通道先验)


# 计算暗通道
def dark_channel(img, size=15):
    b, g, r = cv2.split(img)
    min_img = cv2.min(cv2.min(r, g), b)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (size, size))
    dark = cv2.erode(min_img, kernel)
    return dark

# 大气光估计
dark = dark_channel(img)
max_dark = np.max(dark)
atmosphere = []
for ch in cv2.split(img):
    atmosphere.append(np.max(ch[dark >= max_dark * 0.99]))

# 透射率估计
transmission = 1 - 0.95 * dark_channel(img / atmosphere)

# 图像恢复
result = np.empty_like(img, dtype=np.float32)
for i in range(3):
    result[:, :, i] = (img[:, :, i].astype(float) - atmosphere[i]) / cv2.max(transmission, 0.1) + atmosphere[i]
dehazed = np.clip(result, 0, 255).astype(np.uint8)

应用:自动驾驶中的场景清晰化

73. 显著性检测


# 谱残差方法
def spectral_residual_saliency(image):
    fft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
    magnitude, phase = cv2.cartToPolar(fft[:, :, 0], fft[:, :, 1])
    
    # 计算对数幅度谱
    log_amplitude = np.log(magnitude)
    # 计算平均光谱
    avg_log_amplitude = cv2.blur(log_amplitude, (3, 3))
    # 计算谱残差
    spectral_residual = log_amplitude - avg_log_amplitude
    
    # 转换回傅里叶域
    real, imag = cv2.polarToCart(cv2.exp(spectral_residual), phase)
    back_fft = cv2.merge([real, imag])
    # 反傅里叶变换
    saliency_map = cv2.dft(back_fft, flags=cv2.DFT_INVERSE | cv2.DFT_SCALE | cv2.DFT_REAL_OUTPUT)
    return cv2.normalize(saliency_map, None, 0, 255, cv2.NORM_MINMAX)

# 应用
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
saliency = spectral_residual_saliency(gray)

应用:智能图像裁剪

74. 稠密光流(Farneback)

# 初始化
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
curr_gray = cv2.cvtColor(curr_frame, cv2.COLOR_BGR2GRAY)

# 计算稠密光流
flow = cv2.calcOpticalFlowFarneback(
    prev_gray, curr_gray, None, 
    pyr_scale=0.5, levels=3, winsize=15, 
    iterations=3, poly_n=5, poly_sigma=1.2, flags=0
)

# 可视化
hsv = np.zeros_like(prev_frame)
mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = ang*180/np.pi/2
hsv[...,1] = 255
hsv[...,2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
flow_rgb = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

应用:视频动作分析

75. 深度学习语义分割


# 加载模型
net = cv2.dnn.readNetFromTensorflow(
    "deeplabv3_cityscapes.pb", 
    "deeplabv3_cityscapes.pbtxt"
)

# 输入处理
blob = cv2.dnn.blobFromImage(
    img, scalefactor=1/127.5, size=(512, 512),
    mean=(127.5, 127.5, 127.5), swapRB=True, crop=False
)
net.setInput(blob)

# 推理
output = net.forward()

# 后处理
output = output.squeeze().transpose(1, 2, 0)
class_map = np.argmax(output, axis=2)

# 上色
colors = np.random.randint(0, 255, (256, 3), dtype=np.uint8)
result = colors[class_map]
result = cv2.resize(result, (img.shape[1], img.shape[0]), 
                   interpolation=cv2.INTER_NEAREST)

应用:无人驾驶场景理解

七、工业级应用(86-100)

86. 目标计数(分水岭优化)


# 预处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (11, 11), 0)
thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# 距离变换
dist_transform = cv2.distanceTransform(thresh, cv2.DIST_L2, 5)
ret, sure_fg = cv2.threshold(dist_transform, 0.7 * np.max(dist_transform), 255, 0)
sure_fg = np.uint8(sure_fg)

# 分水岭分割
unknown = cv2.subtract(thresh, sure_fg)
ret, markers = cv2.connectedComponents(sure_fg)
markers += 1
markers[unknown == 255] = 0
markers = cv2.watershed(img, markers)

# 计数
num_objects = np.max(markers) - 1  # 减去背景标记
print(f"检测到 {num_objects} 个物体")

应用:仓库货物自动盘点

87. 手势识别


def detect_gesture(hand_contour):
    # 凸包检测
    hull = cv2.convexHull(hand_contour, returnPoints=False)
    defects = cv2.convexityDefects(hand_contour, hull)
    
    # 手指计数
    finger_count = 0
    for i in range(defects.shape[0]):
        s, e, f, d = defects[i, 0]
        far = tuple(hand_contour[f][0])
        if d > 10000:  # 阈值过滤
            finger_count += 1
    
    # 确定手势
    gestures = ["拳", "剪刀", "布", "三指", "四指", "五指"]
    return gestures[min(finger_count, len(gestures)-1)]

88. 车道线检测系统


# 透视变换
src = np.float32([[frame_w//2-30, frame_h*0.65], 
                  [frame_w//2+30, frame_h*0.65],
                  [frame_w-50, frame_h], 
                  [50, frame_h]])
dst = np.float32([[0,0], [frame_w,0], [frame_w, frame_h], [0,frame_h]])
M = cv2.getPerspectiveTransform(src, dst)
warped = cv2.warpPerspective(frame, M, (frame_w, frame_h))

# 车道线检测
gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=30, 
                        minLineLength=20, maxLineGap=300)

# 车道拟合
left_lines, right_lines = [], []
for line in lines:
    for x1,y1,x2,y2 in line:
        slope = (y2-y1)/(x2-x1) if x2!=x1 else 9999
        if slope < -0.5: left_lines.append((x1,y1,x2,y2))
        elif slope > 0.5: right_lines.append((x1,y1,x2,y2))
        
# 计算平均线
def average_line(lines):
    if not lines: return None
    avg_line = np.mean(np.array(lines), axis=0)
    return avg_line.astype(int)

left_avg = average_line(left_lines)
right_avg = average_line(right_lines)

# 绘制车道
road = warped.copy()
if left_avg is not None:
    cv2.line(road, (left_avg[0], left_avg[1]), 
             (left_avg[2], left_avg[3]), (0,0,255), 5)
if right_avg is not None:
    cv2.line(road, (right_avg[0], right_avg[1]), 
             (right_avg[2], right_avg[3]), (0,0,255), 5)

应用:自动驾驶核心功能

89. 三维重建(多视角)

# 特征匹配
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)
matches = matcher.match(des1, des2)
matches = sorted(matches, key=lambda x: x.distance)[:100]

# 相机标定参数
K = np.array([[focal, 0, w/2], [0, focal, h/2], [0,0,1]])

# 本质矩阵计算
points1 = np.float32([kp1[m.queryIdx].pt for m in matches])
points2 = np.float32([kp2[m.trainIdx].pt for m in matches])
E, mask = cv2.findEssentialMat(points1, points2, K, cv2.RANSAC, 0.999, 1.0)

# 恢复姿态
_, R, t, mask = cv2.recoverPose(E, points1, points2, K, mask=mask)

# 三角测量
points4D = cv2.triangulatePoints(
    np.hstack([np.eye(3), np.zeros((3,1))]), 
    np.hstack([R, t]), 
    points1.T, points2.T
)
points3D = points4D[:3] / points4D[3]

应用:文物数字化重建

90. 异常检测(深度学习)

# 加载自编码器
net = cv2.dnn.readNetFromONNX("autoencoder.onnx")

# 特征提取
input_blob = cv2.dnn.blobFromImage(
    img, scalefactor=1/255., size=(256,256),
    mean=(0.485, 0.456, 0.406), swapRB=True
)
net.setInput(input_blob)
output_blob = net.forward()

# 异常分数计算
reconstruction = output_blob.squeeze().transpose(1,2,0)
reconstruction = cv2.resize(reconstruction, (img.shape[1], img.shape[0]))
original = cv2.resize(input_blob.squeeze().transpose(1,2,0), 
                      (img.shape[1], img.shape[0]))

anomaly_map = np.mean(np.abs(original - reconstruction), axis=2)
anomaly_score = np.max(anomaly_map)

# 异常区域标注
if anomaly_score > 0.2:
    contours = cv2.findContours(
        (anomaly_map > 0.2).astype(np.uint8), 
        cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
    )[0]
    for cnt in contours:
        x,y,w,h = cv2.boundingRect(cnt)
        cv2.rectangle(img, (x,y), (x+w,y+h), (0,0,255), 2)
    cv2.putText(img, f"异常检测! 分数: {anomaly_score:.3f}", 
               (10,30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)

应用:工业质检

八、前沿应用(91-100)

91. 实时虚拟试穿

# 身体姿态估计
net = cv2.dnn.readNetFromTensorflow("pose_net.pb")
blob = cv2.dnn.blobFromImage(img, 1.0, (368,368), (127.5,127.5,127.5), swapRB=True)
net.setInput(blob)
output = net.forward()

# 关键点提取
keypoints = []
for i in range(output.shape[1]):
    heatMap = output[0, i, :, :]
    _, conf, _, point = cv2.minMaxLoc(heatMap)
    if conf > 0.1:
        keypoints.append((point[0], point[1]))

# 三角网格变形
def TPS_transform(src, dst, points):
    tps = cv2.createThinPlateSplineShapeTransformer()
    matches = [cv2.DMatch(i, i, 0) for i in range(len(src))]
    tps.estimateTransformation(np.array([src]), np.array([dst]), matches)
    return tps.applyTransformation(np.array([points]))[1]

# 应用变形
garment = cv2.imread("garment.png", cv2.IMREAD_UNCHANGED)
mesh_points = get_garment_mesh(garment)
transformed_mesh = TPS_transform(garment_points, keypoints, mesh_points)

# 融合渲染
result = warp_image(garment, transformed_mesh)
final = blend_images(img, result)

应用:虚拟时尚

92. 神经风格迁移(实时)


# 加载FastStyleTransfer模型
net = cv2.dnn.readNetFromTorch("style_model.t7")

# 视频流处理
while True:
    ret, frame = cap.read()
    blob = cv2.dnn.blobFromImage(
        frame, 1.0, (400,400), 
        (103.939, 116.779, 123.680), 
        swapRB=False, crop=False
    )
    net.setInput(blob)
    output = net.forward()
    
    # 后处理
    output = output.reshape((3, output.shape[2], output.shape[3]))
    output[0] += 103.939
    output[1] += 116.779
    output[2] += 123.680
    output = output.transpose(1, 2, 0)
    output = np.clip(output, 0, 255)
    output = output.astype(np.uint8)
    
    cv2.imshow("Artistic Style", output)

应用:实时视频特效

93. 聚焦堆栈融合


# 多焦点图像序列
images = [cv2.imread(f"focus{i}.jpg") for i in range(10)]
focus_maps = []
laplacian = cv2.Laplacian(cv2.cvtColor(images[0], cv2.COLOR_BGR2GRAY), cv2.CV_64F)

# 锐度图计算
sharpness_maps = []
for img in images:
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    lap = cv2.Laplacian(gray, cv2.CV_64F)
    sharpness = cv2.GaussianBlur(np.abs(lap), (5,5), 0)
    sharpness_maps.append(sharpness)

# 焦点堆栈融合
fused = np.zeros_like(images[0], dtype=np.float32)
for ch in range(3):
    channel_stack = np.array([img[:,:,ch] for img in images])
    weight_stack = np.array(sharpness_maps)
    weight_stack = np.expand_dims(weight_stack, axis=3)
    weight_sum = np.sum(weight_stack, axis=0)
    weight_sum[weight_sum < 1e-5] = 1e-5  # 避免除零
    fused_ch = np.sum(channel_stack * weight_stack, axis=0) / weight_sum
    fused[:,:,ch] = fused_ch

fused_img = np.clip(fused, 0, 255).astype(np.uint8)

应用:显微摄影

94. 水下图像增强


# 颜色校正
lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
lab[:,:,0] = clahe.apply(lab[:,:,0])
enhanced_lab = cv2.cvtColor(lab, cv2.COLOR_Lab2BGR)

# 蓝光修正
hsv = cv2.cvtColor(enhanced_lab, cv2.COLOR_BGR2HSV)
blue_range = cv2.inRange(hsv, (90, 50, 50), (130, 255, 255))
enhanced_lab = cv2.inpaint(enhanced_lab, blue_range, 3, cv2.INPAINT_TELEA)

# 对比度增强
ycrcb = cv2.cvtColor(enhanced_lab, cv2.COLOR_BGR2YCrCb)
ycrcb[:,:,0] = cv2.equalizeHist(ycrcb[:,:,0])
final = cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2BGR)

应用:海洋探索

95. 皮肤分析系统


def analyze_skin(image):
    # 人脸检测
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    faces = face_cascade.detectMultiScale(image, 1.3, 5)
    if len(faces) == 0: return None
    
    # 提取ROI
    (x,y,w,h) = faces[0]
    face_roi = image[y:y+h, x:x+w]
    
    # 皮肤分割
    lab = cv2.cvtColor(face_roi, cv2.COLOR_BGR2Lab)
    low_thresh = np.array([0, 120, 140]) 
    high_thresh = np.array([255, 140, 165])
    mask = cv2.inRange(lab, low_thresh, high_thresh)
    mask = cv2.medianBlur(mask, 5)
    
    # 分析指标
    smoothness = cv2.Laplacian(face_roi, cv2.CV_64F).var()
    redness = np.mean(face_roi[mask == 255][:,2])
    pores = np.count_nonzero(cv2.morphologyEx(mask, cv2.MORPH_OPEN, 
                                            cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))))
    
    return {
        "光滑度": smoothness,
        "泛红指数": redness,
        "毛孔密度": pores / np.count_nonzero(mask) * 1000
    }

96. 植物健康分析


def plant_health_analysis(image):
    # 叶脉提取
    lab = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)
    l, a, b = cv2.split(lab)
    clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
    enhanced_l = clahe.apply(l)
    
    # 叶脉分割
    vein_mask = cv2.adaptiveThreshold(enhanced_l, 255, 
                                      cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                      cv2.THRESH_BINARY_INV, 11, 2)
    vein_mask = cv2.morphologyEx(vein_mask, cv2.MORPH_OPEN, 
                                cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)))
    
    # 计算参数
    vein_length = np.sum(vein_mask > 0) / image.size[0] * 1000  # 标准化脉长
    health_score = 0.6 * np.mean(b) + 0.4 * (255 - np.mean(a))  # 健康指数(越高越好)
    
    return vein_mask, {
        "叶脉密度": vein_length,
        "健康指数": health_score,
        "缺素症状": "有" if np.mean(a) > 140 else "无"
    }

97. 人群密度估计


def crowd_density_estimation(image):
    # 加载密度图模型
    net = cv2.dnn.readNetFromCaffe("MCNN.prototxt", "MCNN.caffemodel")
    
    # 预处理
    blob = cv2.dnn.blobFromImage(image, 1, (800, 600), (0,0,0), False, False)
    net.setInput(blob)
    
    # 密度图生成
    density_map = net.forward()
    
    # 人数估计
    count = np.sum(density_map)
    
    # 可视化
    norm_density = cv2.normalize(density_map, None, 0, 255, cv2.NORM_MINMAX)
    norm_density = cv2.applyColorMap(np.uint8(norm_density), cv2.COLORMAP_JET)
    norm_density = cv2.resize(norm_density, (image.shape[1], image.shape[0]))
    
    blended = cv2.addWeighted(image, 0.7, norm_density, 0.3, 0)
    cv2.putText(blended, f"人数: {int(count)}", (10,30), 
               cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
    
    return blended

98. 动态全息显示


def generate_hologram(image, wavelength=532e-9, z=0.1):
    """模拟菲涅尔全息图生成"""
    # 生成空间坐标
    h, w = image.shape[:2]
    x = np.linspace(-w//2, w//2, w)
    y = np.linspace(-h//2, h//2, h)
    xx, yy = np.meshgrid(x, y)
    
    # 计算全息图
    hologram = np.zeros((h, w), dtype=np.complex128)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY).astype(float)/255
    
    for i in range(h):
        for j in range(w):
            if gray[i,j] > 0.1:  # 忽略暗区
                # 菲涅尔衍射计算
                r = np.sqrt((xx - j)**2 + (yy - i)**2 + z**2)
                hologram += gray[i,j] * np.exp(1j * 2 * np.pi * r / wavelength) / r
    
    # 提取相位信息
    phase = np.angle(hologram)
    phase_normalized = (phase + np.pi) / (2 * np.pi) * 255
    
    return phase_normalized.astype(np.uint8)

99. 工业尺寸测量


def industrial_measurement(image, reference_width):
    # 预处理
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    edges = cv2.Canny(blur, 50, 150)
    
    # 寻找轮廓
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    # 测量结果
    results = []
    for cnt in contours:
        # 筛选合理大小轮廓
        area = cv2.contourArea(cnt)
        if area < 500: continue
        
        # 最小外接矩形
        rect = cv2.minAreaRect(cnt)
        width, height = rect[1]
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        
        # 像素到实际尺寸转换
        actual_width = min(width, height) * reference_width
        actual_height = max(width, height) * reference_width
        
        results.append({
            "box": box,
            "width": actual_width,
            "height": actual_height,
            "area": area * (reference_width ** 2)
        })
    
    return results

100. 实时手势交互系统


def gesture_control_system():
    # 初始化
    cap = cv2.VideoCapture(0)
    hands = mp.solutions.hands.Hands(max_num_hands=1)
    
    while True:
        ret, frame = cap.read()
        if not ret: break
        
        # 手势识别
        rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        results = hands.process(rgb)
        
        if results.multi_hand_landmarks:
            landmarks = results.multi_hand_landmarks[0].landmark
            
            # 关键点提取
            fingertips = [
                (int(landmarks[4].x * w), int(landmarks[4].y * h)),  # 拇指
                (int(landmarks[8].x * w), int(landmarks[8].y * h)),  # 食指
                (int(landmarks[12].x * w), int(landmarks[12].y * h)),  # 中指
                (int(landmarks[16].x * w), int(landmarks[16].y * h)),  # 无名指
                (int(landmarks[20].x * w), int(landmarks[20].y * h)),  # 小指
            ]
            
            # 手势识别
            extended_fingers = 0
            for fingertip in fingertips:
                # 计算与掌心距离
                center_x = int(landmarks[0].x * w)
                center_y = int(landmarks[0].y * h)
                distance = np.sqrt((fingertip[0]-center_x)**2 + (fingertip[1]-center_y)**2)
                
                if distance > 100:  # 阈值判断
                    extended_fingers += 1
            
            # 指令映射
            commands = {
                0: "握拳",
                1: "食指",
                2: "剪刀手",
                3: "三指",
                4: "四指",
                5: "手掌"
            }
            command = commands.get(extended_fingers, "未知")
            
            # 绘制界面
            cv2.circle(frame, (center_x, center_y), 8, (0,255,0), -1)
            for tip in fingertips:
                cv2.circle(frame, tip, 6, (0,0,255), -1)
            cv2.putText(frame, f"命令: {command}", (10,30), 
                       cv2.FONT_HERSHEY_SIMPLEX, 1, (0,255,0), 2)
    
    cap.release()

学习路径与资源推荐

OpenCV能力矩阵图


学习资源推荐

  1. 官方资源​:

    • OpenCV官方文档
    • OpenCV Wiki
  2. 图书推荐​:

    • 《Learning OpenCV 4》Adrian Kaehler著
    • 《OpenCV 4.x with Python By Example》Prateek Joshi著
  3. 在线课程​:

    • Coursera: Deep Learning for Computer Vision
    • Udemy: OpenCV Bootcamp
  4. 实战项目​:

    • Kaggle竞赛:图像分类、物体检测
    • GitHub仓库:open-smartcamera

关注我们并继续了解更多干货!OpenCv与人工智能!


开启你的计算机视觉专家之旅

#OpenCV #计算机视觉 #人工智能 #工业视觉 #深度学习


网站公告

今日签到

点亮在社区的每一天
去签到