效果图

相关算法

形态学变换,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')

1674659699624.png

膨胀

# 膨胀
# 作用:跟在侵蚀操作后去噪点,把两个分开的部分连接起来
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)

output.png

张开

# 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')

output.png

闭合

# 闭合:closing
# 先膨胀再侵蚀,主要用于闭合主体内的小洞,或者一些黑色的点
kernel = np.ones((20,20),dtype=np.int8)
closing1 = cv2.morphologyEx(gray.copy(),cv2.MORPH_CLOSE,kernel)

output.png

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')

1.pngoutput.png

实战

简单来说,先对每一帧进行二值化处理,之后进行侵蚀、膨胀、闭合,利用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()
最后修改:2023 年 01 月 25 日
如果觉得我的文章对你有用,请随意赞赏