【发布时间】: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”中
调试
我尝试在不裁剪的情况下打印出图像,它看起来很正常。但是,一旦我裁剪它,它就会返回一个空数组 []。
谁能帮我找出我做错了什么?抱歉我的描述太长了!非常感谢!
【问题讨论】:
-
message
size.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(...)- 因此您以错误的顺序分配它们。
标签: python opencv video-processing