news 2026/7/14 2:42:26

OpenCV计算机视觉实战:从图像处理到AI视觉完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenCV计算机视觉实战:从图像处理到AI视觉完整指南

这次我们来系统梳理OpenCV的核心知识体系。作为计算机视觉领域最基础且应用最广泛的库,OpenCV涵盖了从图像处理到AI视觉的完整技术栈。无论你是刚入门的新手,还是需要快速回顾核心概念的在职开发者,这篇文章都能帮你建立清晰的OpenCV知识框架。

OpenCV最值得关注的特点是它的跨平台性和功能完整性。从基础的图像读写、像素操作,到高级的图像分割、目标检测、特征提取,再到实际应用的人脸识别、边缘检测,OpenCV提供了一站式的解决方案。更重要的是,它支持CPU和GPU加速,可以在各种硬件环境下运行,从树莓派到服务器集群都能胜任。

本文将带你从OpenCV环境配置开始,逐步深入图像处理的核心算法,最后通过多个实战案例展示如何将这些技术应用到实际项目中。我们会重点讲解每个知识点的原理、使用场景和代码实现,确保你能真正掌握而不仅仅是了解。

1. OpenCV核心能力速览

能力项说明
图像处理基础图像读写、像素操作、色彩空间转换、几何变换
图像分割阈值分割、边缘检测、区域生长、分水岭算法
目标检测传统方法+HOG/SVM,深度学习+YOLO/SSD
特征提取角点检测、SIFT、SURF、ORB特征描述子
图像滤波均值滤波、高斯滤波、中值滤波、双边滤波
人脸识别Haar级联检测、LBPH识别、深度学习模型
硬件支持CPU优化、GPU加速(CUDA)、多平台部署
语言支持Python、C++、Java、JavaScript等多语言接口
适用场景工业检测、安防监控、医疗影像、自动驾驶、AR/VR

2. OpenCV适用场景与使用边界

OpenCV最适合需要快速原型开发和实际部署的计算机视觉项目。在工业领域,它可以用于产品质检、尺寸测量;在安防领域,支持人脸识别、车辆检测;在医疗领域,辅助医学影像分析;在教育领域,作为计算机视觉入门的最佳实践工具。

但是OpenCV也有其使用边界。对于需要极高精度的复杂场景,纯传统视觉方法可能不如深度学习模型;对于实时性要求极高的应用,需要结合硬件加速和算法优化;对于商业级产品,需要考虑算法专利和授权问题。

特别需要注意的是,涉及人脸识别、生物特征等敏感技术时,必须严格遵守隐私保护法规,确保数据采集和使用符合法律要求。在实际部署前,务必进行充分的测试和效果验证。

3. 环境准备与前置条件

3.1 操作系统要求

  • Windows 7/10/11(推荐Windows 10+)
  • Ubuntu 16.04+ / CentOS 7+
  • macOS 10.14+
  • 也支持嵌入式平台如树莓派、Jetson Nano等

3.2 Python环境配置

# 创建虚拟环境(推荐) python -m venv opencv_env # Windows激活 opencv_env\Scripts\activate # Linux/macOS激活 source opencv_env/bin/activate # 安装基础依赖 pip install numpy matplotlib

3.3 OpenCV安装方式

# 基础版本(CPU only) pip install opencv-python # 完整版本(包含contrib模块) pip install opencv-contrib-python # 如果需要GPU支持(CUDA) pip install opencv-python-headless

3.4 验证安装

import cv2 print(f"OpenCV版本: {cv2.__version__}") # 检查CUDA支持(如果有GPU) print(f"CUDA设备数: {cv2.cuda.getCudaEnabledDeviceCount()}")

4. 图像处理基础实战

4.1 图像读取与显示

import cv2 import numpy as np # 读取图像 img = cv2.imread('test.jpg') print(f"图像尺寸: {img.shape}") # (高度, 宽度, 通道数) # 显示图像 cv2.imshow('Original Image', img) cv2.waitKey(0) # 等待按键 cv2.destroyAllWindows() # 保存图像 cv2.imwrite('output.jpg', img)

4.2 色彩空间转换

# BGR转灰度图 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # BGR转HSV(用于颜色识别) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # BGR转RGB(用于matplotlib显示) rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

4.3 图像几何变换

# 缩放 resized = cv2.resize(img, (640, 480)) # 旋转 (h, w) = img.shape[:2] center = (w // 2, h // 2) matrix = cv2.getRotationMatrix2D(center, 45, 1.0) # 旋转45度 rotated = cv2.warpAffine(img, matrix, (w, h)) # 仿射变换 pts1 = np.float32([[50,50], [200,50], [50,200]]) pts2 = np.float32([[10,100], [200,50], [100,250]]) matrix = cv2.getAffineTransform(pts1, pts2) affine = cv2.warpAffine(img, matrix, (w, h))

5. 图像滤波技术详解

5.1 常用滤波算法对比

滤波类型适用场景优点缺点
均值滤波简单噪声去除计算速度快边缘模糊
高斯滤波高斯噪声保持边缘较好计算量稍大
中值滤波椒盐噪声有效去除孤立噪声点边缘可能失真
双边滤波保边去噪保持边缘清晰计算复杂度高

5.2 滤波代码实现

# 均值滤波 blur = cv2.blur(img, (5, 5)) # 高斯滤波 gaussian = cv2.GaussianBlur(img, (5, 5), 0) # 中值滤波 median = cv2.medianBlur(img, 5) # 双边滤波 bilateral = cv2.bilateralFilter(img, 9, 75, 75) # 自定义卷积核 kernel = np.ones((5, 5), np.float32) / 25 custom = cv2.filter2D(img, -1, kernel)

5.3 滤波效果评估

import matplotlib.pyplot as plt # 显示滤波效果对比 plt.figure(figsize=(12, 8)) plt.subplot(231), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.title('Original'), plt.axis('off') plt.subplot(232), plt.imshow(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB)) plt.title('Mean Filter'), plt.axis('off') plt.subplot(233), plt.imshow(cv2.cvtColor(gaussian, cv2.COLOR_BGR2RGB)) plt.title('Gaussian Filter'), plt.axis('off') plt.subplot(234), plt.imshow(cv2.cvtColor(median, cv2.COLOR_BGR2RGB)) plt.title('Median Filter'), plt.axis('off') plt.subplot(235), plt.imshow(cv2.cvtColor(bilateral, cv2.COLOR_BGR2RGB)) plt.title('Bilateral Filter'), plt.axis('off') plt.tight_layout() plt.show()

6. 边缘检测技术实战

6.1 边缘检测算法原理

边缘检测是图像处理中的重要任务,用于识别图像中亮度明显变化的点。OpenCV提供了多种边缘检测算法:

  • Sobel算子:一阶微分,检测方向性边缘
  • Laplacian算子:二阶微分,对噪声敏感但定位准确
  • Canny算法:多阶段算法,效果最优的经典方法

6.2 Canny边缘检测详解

# Canny边缘检测步骤 def canny_edge_detection(image, low_threshold=50, high_threshold=150): # 1. 转灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 2. 高斯模糊降噪 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 3. Canny边缘检测 edges = cv2.Canny(blurred, low_threshold, high_threshold) return edges # 测试不同阈值效果 edges_weak = canny_edge_detection(img, 30, 90) edges_medium = canny_edge_detection(img, 50, 150) edges_strong = canny_edge_detection(img, 100, 200) # 显示结果对比 plt.figure(figsize=(15, 5)) plt.subplot(131), plt.imshow(edges_weak, cmap='gray') plt.title('Weak Edges (30, 90)'), plt.axis('off') plt.subplot(132), plt.imshow(edges_medium, cmap='gray') plt.title('Medium Edges (50, 150)'), plt.axis('off') plt.subplot(133), plt.imshow(edges_strong, cmap='gray') plt.title('Strong Edges (100, 200)'), plt.axis('off') plt.tight_layout() plt.show()

6.3 边缘检测在工业中的应用

# 工业零件边缘检测示例 def industrial_edge_detection(image_path): # 读取图像 img = cv2.imread(image_path) # 预处理:转灰度、降噪、增强对比度 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (7, 7), 0) # 自适应阈值处理 thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # 边缘检测 edges = cv2.Canny(thresh, 50, 150) # 查找轮廓 contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 绘制轮廓 result = img.copy() cv2.drawContours(result, contours, -1, (0, 255, 0), 2) return result # 使用示例 industrial_result = industrial_edge_detection('industrial_part.jpg') cv2.imshow('Industrial Detection', industrial_result) cv2.waitKey(0) cv2.destroyAllWindows()

7. 图像分割技术深入

7.1 阈值分割方法

阈值分割是最基础的图像分割技术,OpenCV提供了多种阈值处理方法:

# 全局阈值分割 ret, thresh1 = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 自适应阈值分割 thresh2 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) # Otsu's二值化 ret, thresh3 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 显示不同阈值方法效果 titles = ['Original', 'Global Threshold', 'Adaptive Mean', "Otsu's"] images = [gray, thresh1, thresh2, thresh3] plt.figure(figsize=(12, 8)) for i in range(4): plt.subplot(2, 2, i+1) plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.axis('off') plt.show()

7.2 分水岭算法

分水岭算法适用于接触物体的分割:

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) markers = markers + 1 markers[unknown == 255] = 0 # 分水岭算法 markers = cv2.watershed(image, markers) image[markers == -1] = [255, 0, 0] # 标记边界为红色 return image, markers # 使用分水岭算法 segmented_img, markers = watershed_segmentation(img.copy()) cv2.imshow('Watershed Segmentation', segmented_img) cv2.waitKey(0)

8. 特征提取与匹配

8.1 关键点检测算法

OpenCV支持多种特征检测算法:

# 初始化特征检测器 sift = cv2.SIFT_create() surf = cv2.xfeatures2d.SURF_create(400) # 需要contrib模块 orb = cv2.ORB_create() # 检测关键点和描述子 keypoints_sift, descriptors_sift = sift.detectAndCompute(gray, None) keypoints_orb, descriptors_orb = orb.detectAndCompute(gray, None) # 绘制关键点 img_sift = cv2.drawKeypoints(img, keypoints_sift, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) img_orb = cv2.drawKeypoints(img, keypoints_orb, None, color=(0, 255, 0), flags=0) # 显示结果 plt.figure(figsize=(12, 6)) plt.subplot(121), plt.imshow(cv2.cvtColor(img_sift, cv2.COLOR_BGR2RGB)) plt.title(f'SIFT Keypoints: {len(keypoints_sift)}'), plt.axis('off') plt.subplot(122), plt.imshow(cv2.cvtColor(img_orb, cv2.COLOR_BGR2RGB)) plt.title(f'ORB Keypoints: {len(keypoints_orb)}'), plt.axis('off') plt.show()

8.2 特征匹配实战

def feature_matching(img1, img2): # 转灰度 gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 使用ORB检测特征 orb = cv2.ORB_create() kp1, des1 = orb.detectAndCompute(gray1, None) kp2, des2 = orb.detectAndCompute(gray2, None) # 特征匹配 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = bf.match(des1, des2) # 按距离排序 matches = sorted(matches, key=lambda x: x.distance) # 绘制匹配结果 result = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None, flags=2) return result # 特征匹配示例 img1 = cv2.imread('object1.jpg') img2 = cv2.imread('object2.jpg') matching_result = feature_matching(img1, img2) cv2.imshow('Feature Matching', matching_result) cv2.waitKey(0) cv2.destroyAllWindows()

9. 目标检测技术实战

9.1 传统目标检测方法

# HOG特征+ SVM分类器的人体检测 def pedestrian_detection(image): # 初始化HOG描述符 hog = cv2.HOGDescriptor() hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 多尺度检测 boxes, weights = hog.detectMultiScale(image, winStride=(8, 8), padding=(32, 32), scale=1.05) # 绘制检测框 for (x, y, w, h) in boxes: cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) return image # 使用示例 pedestrian_img = cv2.imread('street.jpg') result = pedestrian_detection(pedestrian_img.copy()) cv2.imshow('Pedestrian Detection', result) cv2.waitKey(0)

9.2 深度学习目标检测

# YOLO目标检测实现 def yolo_detection(image_path, config_path, weights_path, classes_path): # 加载YOLO网络 net = cv2.dnn.readNetFromDarknet(config_path, weights_path) # 使用GPU加速(如果可用) net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) # 读取类别名称 with open(classes_path, 'r') as f: classes = [line.strip() for line in f.readlines()] # 读取图像 image = cv2.imread(image_path) height, width = image.shape[:2] # 构建blob blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), swapRB=True, crop=False) net.setInput(blob) # 前向传播 outputs = net.forward() # 处理检测结果 boxes, confidences, class_ids = [], [], [] for output in outputs: for detection in output: scores = detection[5:] class_id = np.argmax(scores) confidence = scores[class_id] if confidence > 0.5: # 置信度阈值 center_x = int(detection[0] * width) center_y = int(detection[1] * height) w = int(detection[2] * width) h = int(detection[3] * height) x = int(center_x - w/2) y = int(center_y - h/2) boxes.append([x, y, w, h]) confidences.append(float(confidence)) class_ids.append(class_id) # 非极大值抑制 indices = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4) # 绘制检测框 if len(indices) > 0: for i in indices.flatten(): x, y, w, h = boxes[i] label = f"{classes[class_ids[i]]}: {confidences[i]:.2f}" cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.putText(image, label, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) return image # 使用示例(需要下载YOLO权重文件) # result = yolo_detection('test.jpg', 'yolov3.cfg', 'yolov3.weights', 'coco.names')

10. 人脸识别系统搭建

10.1 人脸检测

def face_detection(image): # 加载Haar级联分类器 face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 人脸检测 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) # 绘制检测框 for (x, y, w, h) in faces: cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2) return image, len(faces) # 实时人脸检测 def realtime_face_detection(): cap = cv2.VideoCapture(0) face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') while True: ret, frame = cap.read() if not ret: break gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.1, 5) for (x, y, w, h) in faces: cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) cv2.imshow('Real-time Face Detection', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # 启动实时检测 # realtime_face_detection()

10.2 人脸识别系统

# 基于LBPH的人脸识别 class FaceRecognizer: def __init__(self): self.recognizer = cv2.face.LBPHFaceRecognizer_create() self.face_cascade = cv2.CascadeClassifier( cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') self.labels = {} self.current_id = 0 def add_training_data(self, image_paths, label): if label not in self.labels: self.labels[label] = self.current_id self.current_id += 1 faces = [] ids = [] for image_path in image_paths: img = cv2.imread(image_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) face_rects = self.face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5) for (x, y, w, h) in face_rects: face_roi = gray[y:y+h, x:x+w] faces.append(face_roi) ids.append(self.labels[label]) return faces, ids def train(self, faces, ids): self.recognizer.train(faces, np.array(ids)) def predict(self, image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) faces = self.face_cascade.detectMultiScale(gray, 1.1, 5) results = [] for (x, y, w, h) in faces: face_roi = gray[y:y+h, x:x+w] label_id, confidence = self.recognizer.predict(face_roi) # 查找标签名称 label_name = [name for name, id in self.labels.items() if id == label_id][0] results.append({ 'label': label_name, 'confidence': confidence, 'bbox': (x, y, w, h) }) return results # 使用示例 recognizer = FaceRecognizer() # 添加训练数据(需要准备实际的人脸图片) # faces, ids = recognizer.add_training_data(['person1_1.jpg', 'person1_2.jpg'], 'Alice') # recognizer.train(faces, ids) # 预测 # result = recognizer.predict(test_image)

11. 性能优化与最佳实践

11.1 图像处理性能优化

import time def performance_optimization_demo(): # 测试图像 img = cv2.imread('large_image.jpg') # 1. 使用ROI(Region of Interest) start_time = time.time() roi = img[100:300, 200:400] # 只处理感兴趣区域 processed_roi = cv2.GaussianBlur(roi, (5, 5), 0) img[100:300, 200:400] = processed_roi roi_time = time.time() - start_time # 2. 图像金字塔降采样处理 start_time = time.time() small = cv2.pyrDown(img) # 降采样 processed_small = cv2.GaussianBlur(small, (5, 5), 0) result = cv2.pyrUp(processed_small) # 上采样 pyramid_time = time.time() - start_time print(f"ROI处理时间: {roi_time:.4f}秒") print(f"金字塔处理时间: {pyramid_time:.4f}秒") # 使用GPU加速(如果可用) def gpu_acceleration(): # 检查CUDA支持 if cv2.cuda.getCudaEnabledDeviceCount() > 0: print("CUDA设备可用,启用GPU加速") # 将数据上传到GPU gpu_img = cv2.cuda_GpuMat() gpu_img.upload(img) # 在GPU上执行操作 gpu_blur = cv2.cuda.createGaussianFilter(cv2.CV_8UC3, cv2.CV_8UC3, (5, 5), 0) gpu_result = gpu_blur.apply(gpu_img) # 下载回CPU result = gpu_result.download() else: print("CUDA设备不可用,使用CPU处理") result = cv2.GaussianBlur(img, (5, 5), 0) return result

11.2 内存管理最佳实践

# 正确的内存管理 def efficient_image_processing(image_path): # 使用with语句确保资源释放 img = cv2.imread(image_path) try: # 处理图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 及时释放不再需要的大内存对象 del img # 显式释放内存 # 继续处理 edges = cv2.Canny(gray, 50, 150) return edges except Exception as e: print(f"处理错误: {e}") return None # 批量处理优化 def batch_processing(image_paths, batch_size=10): results = [] for i in range(0, len(image_paths), batch_size): batch_paths = image_paths[i:i + batch_size] batch_results = [] for path in batch_paths: try: result = process_single_image(path) batch_results.append(result) except Exception as e: print(f"处理 {path} 时出错: {e}") batch_results.append(None) results.extend(batch_results) # 强制垃圾回收 import gc gc.collect() return results

12. 常见问题与解决方案

12.1 安装与导入问题

问题现象可能原因解决方案
ModuleNotFoundError: No module named 'cv2'OpenCV未安装或环境问题pip install opencv-python或检查Python环境
导入成功但函数调用报错版本不兼容或模块缺失安装完整版:pip install opencv-contrib-python
CUDA相关函数报错GPU驱动或CUDA工具包问题检查CUDA安装,或使用CPU版本

12.2 运行时常见错误

# 健壮的图像处理函数 def robust_image_processing(image_path): try: # 检查文件是否存在 if not os.path.exists(image_path): raise FileNotFoundError(f"图像文件不存在: {image_path}") # 读取图像 img = cv2.imread(image_path) if img is None: raise ValueError("无法读取图像文件,可能格式不支持") # 检查图像尺寸 if img.size == 0: raise ValueError("图像尺寸为0,可能文件损坏") # 处理图像 result = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return result except Exception as e: print(f"图像处理错误: {e}") return None # 处理不同图像格式 def handle_different_formats(image_path): # 支持的图像格式 supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff'] file_ext = os.path.splitext(image_path)[1].lower() if file_ext not in supported_formats: print(f"不支持的图像格式: {file_ext}") return None return cv2.imread(image_path)

12.3 性能问题排查

def performance_profiling(): import cProfile import pstats def processing_function(): img = cv2.imread('test.jpg') for i in range(100): # 模拟复杂处理 blurred = cv2.GaussianBlur(img, (5, 5), 0) edges = cv2.Canny(blurred, 50, 150) # 性能分析 profiler = cProfile.Profile() profiler.enable() processing_function() profiler.disable() stats = pstats.Stats(profiler) stats.sort_stats('cumulative') stats.print_stats(10) # 显示前10个最耗时的函数 # 内存使用监控 def memory_usage_monitor(): import psutil import os process = psutil.Process(os.getpid()) memory_before = process.memory_info().rss / 1024 / 1024 # MB # 执行图像处理 img = cv2.imread('large_image.jpg') result = cv2.GaussianBlur(img, (15, 15), 0) memory_after = process.memory_info().rss / 1024 / 1024 print(f"内存使用: {memory_before:.2f} MB -> {memory_after:.2f} MB") print(f"内存增加: {memory_after - memory_before:.2f} MB")

13. 实际项目应用案例

13.1 文档扫描仪应用

def document_scanner(image): # 转换为灰度图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 高斯模糊 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 边缘检测 edged = cv2.Canny(blurred, 75, 200) # 查找轮廓 contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5] # 寻找文档轮廓 screen_cnt = None for contour in contours: peri = cv2.arcLength(contour, True) approx = cv2.approxPolyDP(contour, 0.02 * peri, True) if len(approx) == 4: screen_cnt = approx break if screen_cnt is not None: # 透视变换 warped = four_point_transform(image, screen_cnt.reshape(4, 2)) return warped else: return image def four_point_transform(image, pts): # 获取输入坐标点 rect = order_points(pts) (tl, tr, br, bl) = rect # 计算新图像的宽度 widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2)) widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2)) maxWidth = max(int(widthA), int(widthB)) # 计算新图像的高度 heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2)) heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2)) maxHeight = max(int(heightA), int(heightB)) # 构造变换矩阵 dst = np.array([ [0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1]], dtype="float32") # 执行透视变换 M = cv2.getPerspectiveTransform(rect, dst) warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight)) return warped def order_points(pts): # 初始化坐标点 rect = np.zeros((4, 2), dtype="float32") # 计算中心点 s = pts.sum(axis=1) rect[0] = pts[np.argmin(s)] # 左上角 rect[2] = pts[np.argmax(s)] # 右下角 # 计算差值 diff = np.diff(pts, axis=1) rect[1] = pts[np.arg
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 2:41:10

LLM-Cookbook大模型实战手册:从Prompt Engineering到RAG开发全流程

今天来看一个对开发者特别实用的项目——LLM-Cookbook大模型实战手册。这是Datawhale团队基于吴恩达大模型系列课程打造的中文实战教程,专门为国内开发者设计,覆盖从Prompt Engineering到RAG开发、模型微调的全流程。这个项目最大的价值在于把吴恩达的11…

作者头像 李华
网站建设 2026/7/14 2:39:28

Sqribble模板驱动出版系统:结构化电子书生成原理与工作流

1. 项目概述:这不是“一键生成”,而是一套被精心封装的出版流水线你有没有过这种经历:手头有一篇写得不错的博客,想把它变成一本像模像样的电子书发给客户当赠品;或者团队刚做完一个培训项目,需要快速出一份…

作者头像 李华
网站建设 2026/7/14 2:38:58

UniAR:统一自回归建模如何简化多模态理解与生成任务

过去一年,多模态大模型的发展路径似乎陷入了一种惯性思维:理解任务用 Encoder 架构,生成任务用 Decoder 架构,两者泾渭分明。这种割裂带来的直接后果是,同一个团队要维护两套模型、两套训练流程,甚至两套技…

作者头像 李华
网站建设 2026/7/14 2:38:43

Stable Diffusion角色与帝皇服饰融合:从模型选择到提示词优化

这类主题最值得先看的不是画得有多像,而是能不能把“帝皇”这种复杂服饰和角色特征稳定地画出来。很多工具一上来就让你调一堆参数,但真正影响效果的往往是模型选择、提示词结构和输出分辨率。如果你手上已经有角色设定图(OC)&…

作者头像 李华
网站建设 2026/7/14 2:38:12

Pandas数据处理从入门到精通:数据清洗、分析与可视化实战

在日常数据处理工作中,我们经常面临Excel表格数据清洗、SQL查询结果分析、时间序列数据处理等任务。传统的手工操作不仅效率低下,而且容易出错。Pandas作为Python生态中最强大的数据处理库,能够帮助我们高效完成这些工作。本文将带你从零开始…

作者头像 李华