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能力矩阵图
学习资源推荐
官方资源:
- OpenCV官方文档
- OpenCV Wiki
图书推荐:
- 《Learning OpenCV 4》Adrian Kaehler著
- 《OpenCV 4.x with Python By Example》Prateek Joshi著
在线课程:
- Coursera: Deep Learning for Computer Vision
- Udemy: OpenCV Bootcamp
实战项目:
- Kaggle竞赛:图像分类、物体检测
- GitHub仓库:open-smartcamera
关注我们并继续了解更多干货!OpenCv与人工智能!
开启你的计算机视觉专家之旅
#OpenCV #计算机视觉 #人工智能 #工业视觉 #深度学习