Python opencv 无法从视频中裁剪帧
Posted
技术标签:
【中文标题】Python opencv 无法从视频中裁剪帧【英文标题】:Python opencv having trouble cropping frames from a video 【发布时间】:2021-08-28 21:05:03 【问题描述】:说明
我对 Python 和 opencv 还很陌生,我想使用 opencv 从视频中裁剪帧。工作流程如下:我打开了一个图像并从鼠标回调函数中获取了一些坐标值。由于视频是用三脚架上的手机拍摄的,我希望感兴趣的区域应该在空间中固定。因此,我可以使用坐标来批量处理其他帧。第一个裁剪的图像已按预期完成并保存,但我在处理其他帧时遇到问题。
代码
导入的包
import cv2
鼠标回调
def get_retval(event, x, y, flags, param):
global ix, iy
if event == cv2.EVENT_LBUTTONDBLCLK:
ix, iy = x, y
获取坐标
def get_cropped():
while True:
count = 1
while count < 4:
cv2.imshow('get reference', img)
k = cv2.waitKey(20) & 0xFF
if k == 27:
break
elif k == ord('a'):
if count == 1:
# upperleft
x1, y1 = ix, iy
elif count == 2:
# upperright
x2, _ = ix, iy
# bottom
elif count == 3:
_, y2 = ix, iy
count += 1
cropped_img = img[y1:y2, x1:x2]
cv2.imshow("cropped", cropped_img)
k = cv2.waitKey(0) & 0xFF
if k == ord('g'):
cv2.imwrite(data_out + "frame_0.png", cropped_img)
return [x1, y1, x2, y2]
cv2.destroyWindow("cropped")
break
else:
cv2.destroyWindow("cropped")
每当双击左侧按钮时,坐标就会被记录下来,我按'a'键记录将值分配给$x_i$和$y_i$,因为i = 1和2。然后,它给我一个裁剪图像的预览。如果图像看起来不错,脚本会返回坐标。
主函数
try:
base_dir = 'xxx'
vid_dir = base_dir + 'yyy'
processing_vid = 'zzz'
data_out = '/Data/Work/'
vidcap = cv2.VideoCapture(vid_dir + processing_vid)
frame_count = 0
while vidcap.isOpened() is True:
retval, image = vidcap.read()
totalFrames = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
if retval is True and frame_count == 0:
cv2.imwrite('/tmp/ref.png', image)
img = cv2.imread('/tmp/ref.png')
cv2.namedWindow('get reference')
img = cv2.resize(img, (960, 540))
cv2.setMouseCallback('get reference', get_retval)
x1, x2, y1, y2 = get_cropped()
if retval is True and frame_count != 0:
cv2.namedWindow('test cropping')
image = cv2.resize(image, (960, 540))
cropped = image[y1:y2, x1:x2]
cv2.imshow('test cropping', cropped)
if frame_count == 10:
break
frame_count += 1
except KeyboardInterrupt:
cv2.destroyAllWindows()
我使用第一帧作为参考来获取坐标。这工作得很好。然后,对于另一帧,我将它们调整为与参考帧相同的大小,并以与函数get_cropped
相同的方式裁剪它们。但是,它只是给我一个错误
来自终端的错误信息
Traceback(最近一次调用最后一次): 文件“/Data/Dropbox/coding/functions/imageProcessing/June11.py”,第 71 行,在 cv2.imshow('测试裁剪', 裁剪) cv2.error: OpenCV(4.5.2) /builddir/build/BUILD/opencv-4.5.2/modules/highgui/src/window.cpp:412: error: (-215:Assertion failed) size.width>0 && size.height>0 在函数“imshow”中
调试
我尝试在不裁剪的情况下打印出图像,它看起来很正常。但是,一旦我裁剪它,它就会返回一个空数组 []。
谁能帮我找出我做错了什么?抱歉我的描述太长了!非常感谢!
【问题讨论】:
messagesize.width>0 && size.height>0
可以表示您有空数组。也许首先使用print()
来查看变量中的内容,也许你有错误的坐标并且它无法裁剪它。或者您的顺序错误 - 它可能需要x1 < x2
、y1 < y2
@furas 是的,我打印了图像,它看起来像一个普通的 numpy 数组。而且,正如您所提到的,一旦我裁剪了图像,它只会输出一个空数组。我认为 x_i 和 y_i 的顺序正确,因为第一帧按照我的预期进行了裁剪
错误在cv2.imshow('test cropping', ...)
行显示问题,但我在您的代码中没有看到这一行。也许你运行不同的代码。
@furas 你是对的!我正在运行一个略有差异的代码。请参阅我更新的问题。非常感谢!
我想我看到了问题——你把坐标弄乱了。 get_cropped()
返回 return [x1, y1, x2, y2]
但您将其分配给 x1, x2, y1, y2 = get_cropped(...)
- 因此您以错误的顺序分配它们。
【参考方案1】:
我无法测试它,但我认为我发现了问题 - 你把坐标弄乱了。
get_cropped()
返回
return [x1, y1, x2, y2]
但你把它分配给
x1, x2, y1, y2 = get_cropped(...)
因此您以错误的顺序分配它们 - 您将 x2
替换为 y1
应该是
x1, y1, x2, y2 = get_cropped(...)
【讨论】:
如果这解决了您的问题,那么您可以将我的答案标记为已接受,几分钟后您可以投票。以上是关于Python opencv 无法从视频中裁剪帧的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 OpenCV 和 Python 通过索引从视频中获取帧?