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)