环境
- python 3.9.13
- pytorch 1.13.1+cpu
- opencv-python 4.5.5.62
人脸检测
import numpy as np
import cv2 as cv
face_cascade = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv.CascadeClassifier('haarcascade_eye.xml')
img = cv.imread('faces.png')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
print(faces)
for (x,y,w,h) in faces:
cv.rectangle(img, (x,y), (x+w, y+h), (255,0,0), 2)
roi_gray = gray[y:y+h, x:x+w]
roi_img = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex, ey, ew, eh) in eyes:
cv.rectangle(roi_img, (ex,ey), (ex+ew, ey+eh), (0,0,255), 2)
cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()
车牌号码识别检测
def preprocess(gray):
"""
对灰度对象进行形态转换(预处理)
:param gray:
:return:
"""
gaussian = cv2.GaussianBlur(gray, (3, 3), 0, 0, cv2.BORDER_DEFAULT)
median = cv2.medianBlur(gaussian, 5)
sobel = cv2.Sobel(median, cv2.CV_64F, dx=1, dy=0, ksize=3)
sobel = np.uint8(np.absolute(sobel))
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=2)
dilation2 = cv2.dilate(erosion, element2, iterations=5)
erosion2 = cv2.erode(dilation2, element1, iterations=4)
return erosion2
def find_plate_number_region(img):
"""
寻找可能是车牌区域的轮廓
:param img:
:return:
"""
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
max_ratio = -1
max_box = None
ratios = []
number = 0
for i in range(len(contours)):
cnt = contours[i]
area = cv2.contourArea(cnt)
if area < 10000:
continue
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int64(box)
a = abs(box[0][0] - box[1][0])
b = abs(box[0][1] - box[1][1])
h = np.sqrt(a ** 2 + b **2)
c = abs(box[1][0] - box[2][0])
d = abs(box[1][1] - box[2][1])
w = np.sqrt(c ** 2 + d **2)
height = int(min(h, w))
weight = int(max(h, w))
area2 = height * weight
r = np.absolute((area2 - area) / area)
if r > 0.6:
continue
ratio = float(weight) / float(height)
print((box, height, weight, area, area2, r, ratio, rect[-1]))
cv2.drawContours(img, [box], 0, 255, 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if ratio > max_ratio:
max_box = box
max_ratio = ratio
if ratio > 5.5 or ratio < 2:
continue
number += 1
ratios.append((box, ratio))
print("总共找到:{}个可能区域!!".format(number))
if number == 1:
return ratios[0][0]
elif number > 1:
filter_ratios = list(filter(lambda t: t[1] >= 2.7 and t[1] <= 5.0, ratios))
size_filter_ratios = len(filter_ratios)
if size_filter_ratios == 1:
return filter_ratios[0][0]
elif size_filter_ratios > 1:
ratios1 = [filter_ratios[i][1] for i in range(size_filter_ratios)]
ratios1 = list(zip(range(size_filter_ratios), ratios1))
ratios1 = sorted(ratios1, key=lambda t: t[1])
idx = ratios1[size_filter_ratios // 2][0]
return filter_ratios[idx][0]
else:
ratios1 = [ratios[i][1] for i in range(number)]
ratios1 = list(zip(range(number), ratios1))
ratios1 = sorted(ratios1, key=lambda t: t[1])
idx = ratios1[-1][0]
return filter_ratios[idx][0]
else:
print("直接返回最接近比例的区域...")
return max_box
def cut(img_or_img_path):
"""
截取车牌区域
:param img:
:return:
"""
if isinstance(img_or_img_path, str):
img = cv2.imread(img_or_img_path)
else:
img = img_or_img_path
rows, cols, _ = img.shape
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dilation = preprocess(gray)
box = find_plate_number_region(dilation)
ys = [box[0, 1], box[1, 1], box[2, 1], box[3, 1]]
xs = [box[0, 0], box[1, 0], box[2, 0], box[3, 0]]
ys_sorted_index = np.argsort(ys)
xs_sorted_index = np.argsort(xs)
x1 = box[xs_sorted_index[0], 0]
x1 = x1 if x1 > 0 else 0
x2 = box[xs_sorted_index[3], 0]
x2 = cols if x2 > cols else x2
y1 = box[ys_sorted_index[0], 1]
y1 = y1 if y1 > 0 else 0
y2 = box[ys_sorted_index[3], 1]
y2 = rows if y2 > rows else y2
img_plate = img[y1:y2, x1:x2]
return img_plate
if __name__=='__main__':
path = 'car2.jpg'
cut_img = cut(path)
print(cut_img.shape)
cv2.imwrite('plat.jpg', cut_img)
cv2.imshow('image', cv2.imread(path))
cv2.imshow('plat', cut_img)
cv2.waitKey(0)
cv2.destroyAllWindows()