【无标题】

python openCV 抑制画面抖动

可以进行实时摄像头防抖和录制视频抖动处理
直接贴代码


class Antishudder():
    def __init__(self,smoth_radius=50,transforms_size=200,video_size=(1920,1080)):
        self.re_init(smoth_radius,transforms_size,video_size)
    
    def re_init(self,smoth_radius,transforms_size,video_size):
        #smoth_radius 平滑窗口
        #transforms_size 记录的曲线长度
        #感觉transforms_size>>smoth_radius 能较好去噪声
        print(137,smoth_radius,transforms_size,video_size)
        self.smoth_radius=smoth_radius
        self.__transforms_size=transforms_size
        self.__transforms=np.zeros((self.__transforms_size,3),np.float32)
        self.prev_gray=None
        self.video_size=tuple(int(x) for x in video_size)
    
    
    @property
    def transforms(self):
        return self.__transforms
    @transforms.setter
    def transforms(self,value):
        self.__transforms=np.vstack([self.__transforms[1:],value])
    
    def smooth(self,trajectory):
        smoothed_trajectory = np.copy(trajectory)
        # 过滤x, y和角度曲线
        for i in range(3):
            smoothed_trajectory[:, i] = self.movingAverage(
                trajectory[:, i], radius=self.smoth_radius)

        return smoothed_trajectory
    def movingAverage(self,curve,radius):
        window_size=2*radius +1
        f=np.ones(window_size)/window_size
        curve_pad=np.lib.pad(curve,(radius,radius),'edge')
        curve_smoothed=np.convolve(curve_pad,f,mode='same')
        curve_smoothed=curve_smoothed[radius:-radius]
        return curve_smoothed
    def fixBorder(self,frame):
        s = frame.shape
        # 在不移动中心的情况下,将图像缩放4%
        T = cv2.getRotationMatrix2D((s[1] / 2, s[0] / 2), 0, 1.04)
        frame = cv2.warpAffine(frame, T, (s[1], s[0]))
        return frame
    
    
    def run(self,inputframe):

        curr_gray = cv2.cvtColor(inputframe, cv2.COLOR_BGR2GRAY)
        if not isinstance(self.prev_gray,np.ndarray):
            self.prev_gray=curr_gray
            return inputframe
        # 检测前一帧的特征点
        prev_pts = cv2.goodFeaturesToTrack(self.prev_gray,
                       maxCorners=200,
                       qualityLevel=0.01,
                       minDistance=30,
                       blockSize=3)
        
        
        # 计算光流(即轨迹特征点) 前一张 当前张 前一张特征
        curr_pts, status, err = cv2.calcOpticalFlowPyrLK(self.prev_gray, curr_gray, prev_pts, None)
        # 检查完整性
        assert prev_pts.shape == curr_pts.shape

        # 只过滤有效点
        idx = np.where(status == 1)[0]
        prev_pts = prev_pts[idx]
        curr_pts = curr_pts[idx]
        #print(72,prev_pts,len(curr_pts),type(prev_pts))
        for point in curr_pts:
            #print(73,point,type(point))
            cv2.putText(inputframe,"+",(int(point[0,0]),int(point[0,1])),cv2.FONT_HERSHEY_SIMPLEX,0.8,(0,0,255))
            
        
        #print("##########\n\n\n")
        # 找到变换矩阵
        m, inlier = cv2.estimateAffine2D(prev_pts, curr_pts)

        # 提取traslation
        dx = m[0, 2]
        dy = m[1, 2]

        # 提取旋转角
        da = np.arctan2(m[1, 0], m[0, 0])

        # 存储转换
        self.transforms = [dx, dy, da]
        
        if self.transforms.shape[0]<3:return inputframe
        # 使用累积变换和计算轨迹
        trajectory = np.cumsum(self.transforms, axis=0)

        # 创建变量来存储平滑的轨迹
        smoothed_trajectory = self.smooth(trajectory)

        # 计算smoothed_trajectory与trajectory的差值
        difference = smoothed_trajectory - trajectory

        # 计算更新的转换数组
        #transforms_smooth = self.transforms + difference
        transforms_smooth = self.transforms
        
        # 从新的转换数组中提取转换
        dx = transforms_smooth[-1, 0]
        dy = transforms_smooth[-1, 1]
        da = transforms_smooth[-1, 2]

        # 根据新的值重构变换矩阵
        m = np.zeros((2, 3), np.float32)
        m[0, 0] = np.cos(da)
        m[0, 1] = -np.sin(da)
        m[1, 0] = np.sin(da)
        m[1, 1] = np.cos(da)
        m[0, 2] = -dx
        m[1, 2] = -dy
        
        #print(239,inputframe.shape,self.video_size)

        # 应用仿射包装到给定的框架
        frame_stabilized = cv2.warpAffine(inputframe, m,self.video_size)

        # Fix border artifacts
        #frame_stabilized = self.fixBorder(frame_stabilized)
        
        #print(247,m)
        self.prev_gray=curr_gray
        return frame_stabilized



#cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture("./data/f4_1.mp4")
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

antib=Antishudder(1000,50,(w,h))
while cap.isOpened():
    success, curr = cap.read()
    if not success:break
    cv2.imshow("A",curr)
    cv2.imshow("B",antib.run(curr) )
    cv2.waitKey(1)






参考链接: link1
参考链接: link2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值