【问题标题】:VideoCapture.read() returns past imageVideoCapture.read() 返回过去的图像
【发布时间】:2018-05-05 04:04:29
【问题描述】:

我在Raspberry pi 上运行python3.6openCV(操作系统为Raspbian

代码大致结构如下。

  1. image 以时间间隔(3~5 分钟)捕获。

  2. 捕获的image 在函数中处理并返回测量值(精度类型)

  3. 迭代 1.~2。直到end_check() 返回True

问题是最近拍摄的image 已过期。看起来它是在大约 10 分钟前拍摄的。最近拍摄的所有图像都迟到了。但是开头拍摄的images 似乎是定时的。并且正确输入的所有.jpg文件中记录的时间 +看起来这个问题是在一个多小时后发生的。 (20~22 次迭代)

Imagescv2 包中被cam0.read() 捕获。以下是代码的主要部分。上传完整代码很长。有人要求,我会更新。

def run(interval,model_list):
    cam0 = cv2.VideoCapture(0)  #Only cam0 is used. cam2 is just to record.
    camdir = "/home/pi/capstone/cam0/"
    cam2 = cv2.VideoCapture(1)
    cam2dir = "/home/pi/capstone/cam2/"
    runNo = 0
    acc_list = list()
    error_list = list()
    end = False
    while(end == False):
        print(runNo,"th run")

        img_name = "%s.jpg" %runNo
        frame, res = cam0.read()   #`res` is the image which will be processed
        cv2.imwrite(os.path.join(camdir,img_name),res)
        _ , cam2pic = cam2.read()
        cv2.imwrite(os.path.join(cam2dir,img_name),cam2pic)
        try:
            temp = Real(res)
            mat = temp.match(model_list)
            acc_list.append([mat,runNo])
            print("Accuracy=", mat)
        except ValueError:
            acc_list.append(["ValueError",runNo])
            error_list.append(["ValueError",runNo])
        except AttributeError:
            acc_list.append(["AttributeError", runNo])
            error_list.append(["AttributeError",runNo])
        except SmallObjectError:
            acc_list.append(["SmallObjectError", runNo])
            error_list.append(["SmallObjectError",runNo])
        runNo = runNo+1
        endNo = 40
        if(runNo/2 > endNo):
            end_check(res, end)
        elif(runNo > endNo):
            end = True
        sleep(interval*60)

    with open("acc_list.txt", "w") as output: #records for tracking errors
        output.write(str(acc_list))
    with open("err_list.txt", "w") as output:
        output.write(str(error_list))
    cam0.release()
    cam2.release()

run(3.5,model_list)

(+) 一些新发现的东西和猜测

  • 随着代码的运行,images 的时间差距越来越大
  • 代码终于显示OpenCV Error
  • 看起来有点像 Video signal 存储在 RAM 中的 R-pi.read() 返回过时的 imageRAM
  • Video signal 存储在RAM 中引发资源问题

下面是OpenCV Error

OpenCV Error: Assertion failed (dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0)) in resize, file /home/pi/opencv/opencv-3.4.0/modules/imgproc/src/resize.cpp, line 4045
Traceback (most recent call last):
  File "runpi.py", line 264, in <module>
    run(3.5,model_list)
  File "runpi.py", line 234, in run
    mat = temp.match(model_list)
  File "runpi.py", line 184, in match
    self.__resize(model.get_m_inform())
  File "runpi.py", line 147, in __resize
    self.mask = cv2.resize(self.mask, None, fx=reratio, fy=reratio, interpolation = inter_method)
cv2.error: /home/pi/opencv/opencv-3.4.0/modules/imgproc/src/resize.cpp:4045: error: (-215) dsize.area() > 0 || (inv_scale_x > 0 && inv_scale_y > 0) in function resize

(+) 部分代码引发错误

这是__.resize() 方法。当我手动处理OpenCV Error 发生的image 时,即使OpenCV Error 指出image 的大小很重要,它也能正常工作。所以我认为这与image 本身或sizemd_inf() 获得无关。无论如何,这是代码。

def __resize(self, md_inf):       
    #md_inf = [219, 122, 132, 171, 262] <-sample
    reratio = md_inf[0]/self.y
    if(reratio>1):
        inter_method = cv2.INTER_LINEAR
    else:
        inter_method = cv2.INTER_AREA

    ###below is line 147###
    self.mask = cv2.resize(self.mask, None, fx=reratio, fy=reratio, interpolation = inter_method)
    temp = np.zeros((md_inf[3], md_inf[4]), np.uint8)
    m_cx, m_cy = md_inf[1:3]

    _, contour, _ = cv2.findContours(self.mask, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

    total_contour = contour[0]
    for ctr in contour[1:]:
        total_contour = np.concatenate((total_contour, ctr), axis =0)
    mmt = cv2.moments(total_contour)
    if(mmt['m00'] < 7500):
        raise SmallObjectError

    self.cy = int(mmt['m10']/mmt['m00']) #y is horrizon axis
    self.cx = int(mmt['m01']/mmt['m00']) #x is vertical axis

    x, y = self.mask.shape

    adjust = m_cx - self.cx + x - temp.shape[0]
    if(adjust > 0):
        m_cx = m_cx - adjust

    temp[(m_cx-self.cx):(m_cx-self.cx) +x, (m_cy-self.cy):(m_cy-self.cy) +y] = self.mask

    self.mask = temp

【问题讨论】:

  • 我怀疑你是“遭受缓冲”。我认为从相机读取的视频数据是缓冲的,如果你不经常读取它,你可能会得到一直在缓冲区中的旧数据。一种解决方案可能是在开始时设置较低的帧速率。另一个可能是启动第二个线程/进程,该线程/进程连续将相机中的图像循环读取到 4 个内存缓冲区中,当你想要一帧时,你只需复制另一个线程填充的最后一个,这样如果你读到 8每秒帧数,最旧的帧永远不会超过 1/2 秒。
  • @MarkSetchell 非常感谢。我可以为这两种解决方案获得一些参考吗?
  • 我在您粘贴的代码中没有看到任何imread...
  • @DanMašek 哦,你是对的。这是一个很大的错误。
  • @DanMašek 更新了代码,而match 并不是真正有用。所以跳过了。谢谢大家指点

标签: image opencv raspberry-pi


【解决方案1】:

我同意Mark Serchell 的评论。我使用的方式是将变量设置为time + x seconds 并检查。 OpenCV 具有跳帧的有用功能,例如cam.grab()。它只会从缓冲区中读取该帧,但不会对其执行任何操作。这样,您可以避免“遭受缓冲”。简单的代码是:

import cv2
import time
cam = cv2.VideoCapture(url)
ret,frame = cam.read()
timeCheck = time.time()
future = 10*60 # delay
while ret:
    if time.time() >= timeCheck:
        ret,frame = cam.read()
        # Do your staff here
        timeCheck = time.time()+future
    else:
        # Read from buffer, but skip it
        ret = cam.grab() # note that grab() function returnt only status code,not the frame

【讨论】:

  • 它仍然显示相同的错误。我什至不知道是什么导致了现在的问题。可能不是因为buffer的问题。
  • 但它看起来解决了buffer 问题。我不能说这是正确的解决方案,因为我不确定它是否解决得很好。我仍然遭受“OpenCV 错误”的困扰。我猜“OpenCV 错误”不是因为“缓冲区”问题,而是“过去的图像返回”是因为“缓冲区”。
  • 好的,我回答了一个关于过去图像问题的问题(如标题所示)。这是另一个问题,但我也会尝试回答。大多数情况下,当没有图像或图像存在问题时会发生此类错误。总是先检查图像,然后再做其他事情。尝试捕获错误并将该帧保存到磁盘以查看该帧是否存在问题。节省时间,在不同的摄像头上测试此代码(Android IP 摄像头应用程序可能很有用)并放弃测试的跳过期。之后,我们可以继续。
  • buffer 的问题已经解决,感谢您的回答。这里描述了我面临的另一个问题。 stackoverflow.com/questions/50236080/…如果你加入这里会很有帮助
猜你喜欢
  • 2019-03-02
  • 1970-01-01
  • 2022-09-26
  • 1970-01-01
  • 2023-03-29
  • 2016-12-13
  • 2015-10-15
  • 2017-03-20
  • 2017-12-24
相关资源
最近更新 更多