效果图
相关算法
形态学变换,Canny边缘检测
形态学变换
形态学变换:基于图像形状的一些简单操作,一般基于单通道图处理(常用灰度图);
一般有两个输入,一是要操作的图片,二是要变换的结构元素或核
两种基本的形态学变换是侵蚀和膨胀,他们的变种也有张开和闭合
侵蚀
# 3x3,1
# 侵蚀
# 作用:去除白色噪点,将两个连起来的形状打散
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./test_imgs/j.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
kernel = np.ones((3,3),dtype=np.int8)
ersion1 = cv2.erode(gray.copy(),kernel,iterations=1)
plt.imshow(ersion1,cmap='gray')
膨胀
# 膨胀
# 作用:跟在侵蚀操作后去噪点,把两个分开的部分连接起来
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./test_imgs/j.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
kernel = np.ones((3,3),dtype=np.int8)
dilation1 = cv2.dilate(gray.copy(),kernel,iterations=1)
张开
# opening,张开
# 侵蚀+膨胀
# 主要用于清除噪点
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./test_imgs/cv.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
kernel = np.ones((10,10),dtype=np.int8)
opening1 = cv2.morphologyEx(gray.copy(),cv2.MORPH_OPEN,kernel)
kernel = np.ones((12,12),dtype=np.int8)
opening2 = cv2.morphologyEx(gray.copy(),cv2.MORPH_OPEN,kernel)
kernel = np.ones((15,15),dtype=np.int8)
opening3 = cv2.morphologyEx(gray.copy(),cv2.MORPH_OPEN,kernel)
fig,(ax1,ax2,ax3,ax4) = plt.subplots(1,4,figsize=(20,8),sharex=True,sharey=True)
ax1.axis('off')
ax1.imshow(gray.copy(),cmap='gray')
ax1.set_title('orginal image')
ax2.axis('off')
ax2.imshow(opening1,cmap='gray')
ax2.set_title('10x10')
ax3.axis('off')
ax3.imshow(opening2,cmap='gray')
ax3.set_title('12x12')
ax4.axis('off')
ax4.imshow(opening3,cmap='gray')
ax4.set_title('15x15')
闭合
# 闭合:closing
# 先膨胀再侵蚀,主要用于闭合主体内的小洞,或者一些黑色的点
kernel = np.ones((20,20),dtype=np.int8)
closing1 = cv2.morphologyEx(gray.copy(),cv2.MORPH_CLOSE,kernel)
Canny边缘检测
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./test_imgs/pumpkin.jpg')
img_fixed = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
edges1 = cv2.Canny(img.copy(),100,200)
edges2 = cv2.Canny(img.copy(),50,200)
edges3 = cv2.Canny(img.copy(),50,100)
fig,(ax2,ax3,ax4) = plt.subplots(1,3,figsize=(20,8),sharex=True,sharey=True)
ax2.axis('off')
ax2.imshow(edges1,cmap='gray')
ax3.axis('off')
ax3.imshow(edges2,cmap='gray')
ax4.axis('off')
ax4.imshow(edges3,cmap='gray')
实战
简单来说,先对每一帧进行二值化处理,之后进行侵蚀、膨胀、闭合,利用cv2.Canny()方法进行检测边缘,再根据cv2.findContours()方法获取边缘点,再利用cv2.boundingRect()获取点的坐标,之后绘制矩形方块即可
import cv2
import numpy as np
import time
cap = cv2.VideoCapture('./videos/raw.mp4')
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
frame_index = 0
fpsTime = time.time()
videoWriter = cv2.VideoWriter('./record_video/out'+str(time.time()) +
'.mp4', cv2.VideoWriter_fourcc(*'H264'), 15, (1080, 1920))
while True:
ret, frame = cap.read()
if frame is None:
break
frame = cv2.resize(frame, (1080, 1920))
img_copy = frame.copy()
# 遮罩手部:可以用手部检测器实现,
frame[1550:1920, 700:1080] = 255
if 154 > frame_index > 50:
# cv2.rectangle(frame,(0,1300),(300,1920),(255,0,255),10)
# cv2.rectangle(frame,(300,1400),(1080,1920),(255,0,255),10)
frame[1300:1920, 0:300] = 255
frame[1400:1920, 300:1080] = 255
if 46 > frame_index > 38:
cv2.rectangle(frame, (300, 400), (600, 1920), (255, 0, 255), 10)
frame[400:1920, 300:600] = 255
# frame[1400:1920,300:1080] = 255
# frame = cv2.rotate(frame,cv2.ROTATE_90_CLOCKWISE)
# 灰度
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 二值化
retval, black_img = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY_INV)
# 腐蚀
kernel = np.ones((3, 3), dtype=np.int8)
erosion = cv2.erode(black_img, kernel, iterations=2)
# 再膨胀,连接主体
kernel = np.ones((10, 10), dtype=np.int8)
dialation = cv2.dilate(erosion, kernel, iterations=2)
# # 在膨胀基础上闭合
kernel = np.ones((10, 10), dtype=np.int8)
closing = cv2.morphologyEx(dialation, cv2.MORPH_CLOSE, kernel)
# # 复制底图
# 再次取边缘、轮廓
edged = cv2.Canny(closing.copy(), 30, 200)
contours, hierarchy = cv2.findContours(edged,
cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for c in contours:
x, y, w, h = cv2.boundingRect(c)
# 过滤
if (300 > w > 100) and (300 > h > 100):
cv2.rectangle(img_copy, (x, y), (x+w, y+h), (0, 255, 0), 10)
frame_index += 1
# time.sleep(0.1)
cTime = time.time()
fps_text = 1/(cTime-fpsTime)
fpsTime = cTime
videoWriter.write(img_copy)
cv2.imshow('demo', img_copy)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()