版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
1 介绍
本文主要介绍OpenCV自带轮廓检索函数findContours()的用法,让我们看看如何在一个二值图像中查找轮廓。函数cv2.findContours() 有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构。轮廓(第二个返回值)是一个Python列表,其中存储这图像中的所有轮廓。每一个轮廓都是一个Numpy 数组,包含对象边界点(x,y)的坐标。
2 代码
import cv2
import numpy as np
import matplotlib.pylab as plt
import os
# 形态学处理
def Process(img):
# 高斯平滑
gaussian = cv2.GaussianBlur(img, (3, 3), 0, 0, cv2.BORDER_DEFAULT)
# 中值滤波
median = cv2.medianBlur(gaussian, 5)
# Sobel算子
# 梯度方向: x
sobel = cv2.Sobel(median, cv2.CV_8U, 1, 0, ksize=3)
# 二值化
ret, binary = cv2.threshold(sobel, 170, 255, cv2.THRESH_BINARY)
# 核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))
# 膨胀
dilation = cv2.dilate(binary, element2, iterations=1)
# 腐蚀
erosion = cv2.erode(dilation, element1, iterations=1)
# 膨胀
dilation2 = cv2.dilate(erosion, element2, iterations=3)
return dilation2
def GetRegion(img):
regions = []
# 查找轮廓
_, contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
area = cv2.contourArea(contour)
if (area < 2000):
continue
eps = 1e-3 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, eps, True)
rect = cv2.minAreaRect(contour)
box = cv2.boxPoints(rect)
box = np.int0(box)
height = abs(box[0][1] - box[2][1])
width = abs(box[0][0] - box[2][0])
ratio = float(width) / float(height)
if (ratio < 5 and ratio > 0.3):
regions.append(box)
return regions
def detect(img_path,cut_pixels):
if not os.path.exists(img_path):
return
img = plt.imread(img_path)
# 灰度化
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
prc = Process(gray)
regions = GetRegion(prc)
new_regions = []
for i in range(0,len(regions)):
if len(regions) == 1:
new_regions = regions
if len(regions) == 2:
new_regions = regions[-1:]
if len(regions) == 3:
new_regions = regions[-2:]
if len(regions) == 4:
new_regions = regions
print('[INFO]:Detect %d license plates' % len(new_regions))
for box in new_regions:
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
print([box])
cv2.imshow('Result', img)
# # 保存结果文件名
cv2.imwrite(os.path.join(os.path.dirname(img_path) + '/images_%d/'%(cut_pixels),os.path.basename(img_path)), img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# print(regions)
return new_regions
if __name__ == '__main__':
# 输入的参数为图片的路径
detect('1.jpg',67)
3 效果展示