生成样本:opencv-python的使用(二)

lamdba
1个月前 阅读 32 点赞 1

这次将做一个简单的运动追踪,可以说是对研究智能算法没啥帮助,仅仅看几个opencv-python提供的函数而已。也不会有第三个教程了……


以下代码可以生成一个avi视频:

import cv2
import numpy as np


class Thing_Frame:  # 其对象能产生方块碰撞动画的每一帧(矩阵)
    def __init__(self,size:"图像尺寸元组",r:"方块中心到顶点的距离",start:"起始位置元组",step:"每一帧移动几个像素"):
        self.sizex = size[0]
        self.sizey = size[1]
        self.step = step
        self.r = r
        
        self.vx = 1   # 初始速度(绝对值必须是1)
        self.vy = 1
        self.x = start[0]
        self.y = start[1]
        
        assert not self.collidex()
        assert not self.collidey()
    def collidex(self):return False if self.r-1 < self.x < self.sizex-self.r else True
    def collidey(self):return False if self.r-1 < self.y < self.sizey-self.r else True
    def __iter__(self):
        while True:
            canvas = np.ones((self.sizey,self.sizex,3),dtype='uint8')*255
            x,y,r = self.x, self.y, self.r
            for dx in range(r):
                for dy in range(r-dx):
                    canvas[y+dy][x+dx] = (0,0,0)
                    canvas[y+dy][x-dx] = (0,0,0)
                    canvas[y-dy][x-dx] = (0,0,0)
                    canvas[y-dy][x+dx] = (0,0,0)
            yield canvas
            for _ in range(self.step):
                if self.collidex():self.vx *= -1    # 若碰撞则反向
                if self.collidey():self.vy *= -1
                self.x += self.vx
                self.y += self.vy
        
        


if __name__ == "__main__":
    SIZE = (600,400)
    video=cv2.VideoWriter("thing.avi", cv2.VideoWriter_fourcc('D','I','V','X'), 30, SIZE)
    for canvas,_ in zip(Thing_Frame(size=SIZE,r=70,start=(200,125),step=5),range(300)):
        video.write(canvas)
    video.release()


如果你有一个不错的代码编辑器,可以把类折叠掉不看,毕竟一点都不重要……(其实这一整段都不重要,不过对python中迭代器有兴趣而不精通的,可以看看)


然后获得了视频文件。这个运动检测的原理十分简单,【仅仅是比对每两帧之间不同的像素而已】,还有一些用于模糊和强调的操作,毕竟视频不像矢量动画这么清晰。整个流程表述为:


-灰度-> -高斯模糊-> -邻帧差-> -阈值-> -膨胀->


先把图像化为灰度图(不涉及颜色,方便处理)并模糊,然后把到这一步的结果逐帧比对(仅仅把相邻两帧的灰度作差,再取绝对值,未改变的像素会呈现黑色),再使高于阈值(比如设阈值为25)的像素全白、低于阈值的像素全黑,最后把得到的白色部分周围加一圈像素(我也不知道有什么用)——cv提供了一个函数来把白色部分框起来,框到的就大致是运动部分了。


代码如下:

import cv2
import numpy as np

class A:
    def __init__(self,vc): self.vc = vc
    def __iter__(self): return self
    def __next__(self):
        success, frame = self.vc.read()
        if success: return frame
        else: raise StopIteration
        
    
def f0(img):        # -灰度->
    return cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
def f1(img):        # -高斯模糊->
    return cv2.GaussianBlur(img,(21,21),0)
def f2(img,lastimg):    # -邻帧差->
    return cv2.absdiff(lastimg,img)
def f3(img):        # -阈值->
    return cv2.threshold(img, 25, 255, cv2.THRESH_BINARY)[1]
def f4(img):        # -膨胀->
    return cv2.dilate(img, None, iterations=2)

a = A(cv2.VideoCapture("thing.avi"))

lastimg2=f1(f0(next(a)))
for frame in a:
    img2 = f1(f0(frame))
    img3 = f2(img2,lastimg2)
    img5 = f4(f3(img3))

    x,y,w,h=cv2.boundingRect(img5) 
    frame=cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2)
    cv2.imshow("frame", frame)
    cv2.imshow("img3", img3)

    if cv2.waitKey(1)&0xFF == ord("q"):break

    lastimg2 = img2

a.vc.release()
cv2.destroyAllWindows()

呃……自己看吧。另外cv2.rectangle函数绘制矩形的方式是,接收绘制前的图像(比如全白图像),返回绘制后的图像。


有摄像头的朋友试试把 cv2.VideoCapture 的参数改成0?


(2018-7-24 于地球)

| 1
登录后可评论,马上登录吧~
评论 ( 3 )
请问我咋运行不了你的两段代码呢~
回复 · 2
1个月前
lamdba 回复 紫色蒲公英 1个月前 回复
哦?是如何报错的?cv2可以导入嘛
紫色蒲公英 回复 lamdba 1个月前 回复
找到问题了!摄像头没开...我说怎么改哪里都没用
相关推荐