使用OpenCV的findContours获取轮廓并切割(python)

本文介绍了如何使用OpenCV进行图像轮廓的检测、绘制及切割。首先通过cv2.findContours函数找到图像中的轮廓,其次利用cv2.rectangle绘制矩形框显示轮廓区域,最后通过数组切片实现轮廓的精确切割。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#1 获取轮廓
OpenCV2获取轮廓主要是用cv2.findContours

import numpy as np
import cv2

image = cv2.imread('test.jpg')
imgray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
#image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 旧版本返回三个参数,新版本返回2个
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

其中,findContours的第二个函数很重要,主要分为 cv2.RETR_LIST, cv2.RETR_TREE, cv2.RETR_CCOMP, cv2.RETR_EXTERNAL,具体含义可参考官方文档

#2 画出轮廓
为了看到自己画了哪些轮廓,可以使用 cv2.boundingRect()函数获取轮廓的范围,即左上角原点,以及他的高和宽。然后用cv2.rectangle()方法画出矩形轮廓

for i in range(0,len(contours)):  
	x, y, w, h = cv2.boundingRect(contours[i])   
	cv2.rectangle(image, (x,y), (x+w,y+h), (153,153,0), 5) 

#3 切割轮廓
轮廓的切割主要是通过数组切片实现的,不过这里有一个小技巧:就是图片切割的w,h是宽和高,而数组讲的是行(row)和列(column)
所以,在切割图片时,数组的高和宽是反过来写的

   newimage=image[y+2:y+h-2,x+2:x+w-2] # 先用y确定高,再用x确定宽
   nrootdir=("E:/cut_image/")
   if not os.path.isdir(nrootdir):
       os.makedirs(nrootdir)
   cv2.imwrite( nrootdir+str(i)+".jpg",newimage) 
   print (i)

这样就可以把确定的轮廓都切割出来了。

### 车牌识别与字符分割的实现方法 车牌识别与字符分割是计算机视觉领域中常见的任务,可以通过PythonOpenCV实现。以下是一个完整的实现方案,包括车牌定位、字符分割以及字符提取的核心步骤。 #### 1. 车牌定位 车牌定位的目标是从输入图像中提取出车牌区域。通常使用缘检测和形态学操作来完成此任务。 ```python import cv2 import numpy as np def locate_license_plate(image): # 转换为灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 高斯模糊以减少噪声 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 应用Canny缘检测 edged = cv2.Canny(blurred, 30, 200) # 查找轮廓 contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) # 假设最大的轮廓是车牌 plate_contour = max(contours, key=cv2.contourArea) # 绘制轮廓返回结果 plate_image = image.copy() cv2.drawContours(plate_image, [plate_contour], -1, (0, 255, 0), 3) return plate_image, plate_contour ``` 上述代码实现了车牌的初步定位[^1]。通过`cv2.findContours`函数查找图像中的轮廓选择面积最大的轮廓作为车牌候选区域。 #### 2. 字符分割 字符分割的目标是从车牌区域中提取出单个字符。这一步需要对车牌图像进行二值化处理,利用轮廓查找技术分离字符。 ```python def segment_characters(plate_image, plate_contour): # 提取车牌区域 x, y, w, h = cv2.boundingRect(plate_contour) plate_roi = plate_image[y:y+h, x:x+w] # 转换为灰度图像二值化 gray_plate = cv2.cvtColor(plate_roi, cv2.COLOR_BGR2GRAY) _, binary_plate = cv2.threshold(gray_plate, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 查找字符轮廓 contours, _ = cv2.findContours(binary_plate.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 对字符轮廓进行排序 sorted_contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[0]) characters = [] for contour in sorted_contours: x, y, w, h = cv2.boundingRect(contour) character = binary_plate[y:y+h, x:x+w] characters.append(character) return characters ``` 字符分割通过`cv2.findContours`函数查找车牌区域中的字符轮廓按从左到右的顺序排列这些轮廓[^1]。每个字符被单独提取出来,以便后续进行字符识别。 #### 3. 字符识别(可选) 字符识别可以使用机器学习或深度学习方法实现。例如,可以训练一个卷积神经网络(CNN)模型来识别字符。以下是基于模板匹配的简单示例: ```python def recognize_characters(characters): # 加载预定义的字符模板 templates = load_character_templates() # 自定义函数,加载字符模板 recognized_chars = [] for char in characters: match_scores = [] for template in templates: result = cv2.matchTemplate(char, template, cv2.TM_CCOEFF_NORMED) _, max_val, _, _ = cv2.minMaxLoc(result) match_scores.append(max_val) # 找到匹配度最高的模板 best_match_index = np.argmax(match_scores) recognized_char = chr(ord('A') + best_match_index) # 假设模板为A-Z recognized_chars.append(recognized_char) return recognized_chars ``` 字符识别部分依赖于预定义的字符模板。对于更复杂的场景,建议使用深度学习框架如TensorFlow或PyTorch训练一个专用的字符识别模型。 #### 示例代码整合 以下是一个完整的示例代码,展示了如何将车牌定位、字符分割和字符识别结合在一起。 ```python image = cv2.imread('car_plate.jpg') # 车牌定位 plate_image, plate_contour = locate_license_plate(image) # 字符分割 characters = segment_characters(plate_image, plate_contour) # 字符识别 recognized_chars = recognize_characters(characters) print("Recognized Characters:", recognized_chars) # 显示结果 cv2.imshow('License Plate Detection', plate_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` ### 注意事项 - 车牌定位的准确性可能受到光照条件、车牌倾斜角度等因素的影响。 - 字符分割需要确保车牌区域清晰且无遮挡。 - 字符识别的性能取决于训练数据的质量和模型的复杂性。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值