【问题标题】:Program abruptly shutting off Raspberry Pi程序突然关闭 Raspberry Pi
【发布时间】:2017-12-14 22:50:11
【问题描述】:

所以我的 Raspberry Pi 上有一个 Python 程序,它在无限循环中运行,每秒从相机中获取一张图像。

每次迭代时,程序都会创建一个使用图像进行处理的线程。该过程包括:一个脚本使用 OpenCV 从图像中提取手机屏幕,另一个脚本从该屏幕中提取 QR 码。

我使用该程序使用预先拍摄的图像来毫无问题地处理它们,但如果我让程序通过一个连续循环,它只会窒息。

经过几次循环迭代并尝试处理图像后,程序意外中断,我的 Raspberry Pi 突然关闭。有谁知道为什么会这样?

我一直在寻找答案,但我的怀疑与线程有关。要么,我的 CPU 或 RAM 超载,内存泄漏,Raspberry Pi 耗电过多

编辑:

从下面的 cmets 看来,Pi 的电源似乎是问题所在。我目前正在使用手机充电器(5.0v,1.0A),它(非常)低于 5.0v,2.5A 推荐的电源,真烦我。当我得到一个新的电源并测试代码时,我会更新这篇文章。

此外,在我的 Windows 笔记本电脑上运行该程序完全没有问题。

这是我的主要脚本:

import picamera
import threading
import time
from processing.qr import get_qr_code
from processing.scan import scan_image

# Thread method
def extract_code(file):

    print 'Thread for: ' + file

    # Scans image to extract phone screen from image and then gets QR code from it
    scan_image(file)
    get_qr_code(file)

    return
# End methods

camera = picamera.PiCamera()

while True:

    time.sleep(1)

    # Make epoch time as file name
    time_epoch = str(int(time.time()))
    image_path = "images/" + time_epoch + ".jpg"

    print "Taking photo: " + str(image_path)

    camera.capture(image_path)

    # Create thread to start processing image
    t = threading.Thread(target=extract_code, args=[time_epoch])
    t.start()

下面是扫描图像的脚本(scan.py) 简而言之,它会拍摄一张图像,对其进行模糊处理、寻找边缘并绘制轮廓,检查是否有一个矩形(例如手机屏幕),然后将其转换并扭曲成一个只有手机屏幕的新图像。

from transform import four_point_transform
import imutils
import numpy as np
import argparse
import cv2
import os

def scan_image(file):

    images_dir = "images/"
    scans_dir = "scans/"
    input_file = images_dir + file + ".jpg"

    print "Scanning image: " + input_file

    # load the image and compute the ratio of the old height
    # to the new height, clone it, and resize it
    image = cv2.imread(input_file)
    ratio = image.shape[0] / 500.0
    orig = image.copy()
    image = imutils.resize(image, height = 500)

    # convert the image to grayscale, blur it, and find edges
    # in the image
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(gray, 75, 200)

    # show the original image and the edge detected image
    print "STEP 1: Edge Detection"

    # find the contours in the edged image, keeping only the
    # largest ones, and initialize the screen contour
    _, cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]

    screenCnt = 0

    # loop over the contours
    for c in cnts:
        # approximate the contour
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)

    # if our approximated contour has four points, then we
    # can assume that we have found our screen
    if len(approx) == 4:
        screenCnt = approx
        break

    # show the contour (outline) of the piece of paper
    print "STEP 2: Find contours of paper"

    # if screenCnt > 0 :
    #   cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)

    # apply the four point transform to obtain a top-down
    # view of the original image

    if screenCnt > 0:
        warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)

        print "STEP 3: Apply perspective transform"

        output = scans_dir + file + "-result.png"

        if not os.path.exists(scans_dir):
            os.makedirs(scans_dir)

        cv2.imwrite(output, imutils.resize(warped, height = 650))

    else:
        print "No screen detected"

这是从图像中扫描二维码的代码:

import os
from time import sleep

def get_qr_code(image_name):

    scans_dir = "scans/"
    codes_dir = "codes/"

    input_scan_path = scans_dir + image_name + "-result.png"
    output_qr_path = codes_dir + image_name + "-result.txt"

    if not os.path.exists(codes_dir):
        os.makedirs(codes_dir)

    if os.path.exists(input_scan_path):

        os.system("zbarimg -q " + input_scan_path + " > " + output_qr_path)

    if os.path.exists(output_qr_path):

        strqrcode = open(output_qr_path, 'r').read()

        # print strqrcode
        print "Results for " + image_name + ": " + strqrcode

    else:
        print "File does not exist"

【问题讨论】:

    标签: python multithreading opencv raspberry-pi computer-vision


    【解决方案1】:

    经过几次循环迭代并尝试处理图像后,程序意外中断,我的 Raspberry Pi 突然关闭。有谁知道为什么会这样?

    我也有类似的经历。我的程序 (C++) 实时处理相机帧意外崩溃。有时在操作系统代码中出现分段错误,有时只是关闭整个电路板。有时程序可执行文件只是变成零字节。

    我花了很长时间寻找内存泄漏或 CPU 峰值或其他类型的编程错误。突然我意识到我的电源不是那么强。我换了一个更强大的新的,我没有更多的问题。

    请参阅link 中的 2.5 A 建议,并检查您的 UPS 是否真正满足此要求。

    【讨论】:

    • 是的,这可能是我的问题(愚蠢的我)。我的 Pi 使用手机充电器提供的 5.0v、1.0A 电源运行。重新打开电路板后,我的 python 文件中的字节数也为零,因此我不得不再次克隆 repo。我将改变我的电源并用结果编辑这篇文章。谢谢多勒伦
    • 感谢您的澄清。有时很难找到真正的 2.5 A。如果是您的情况,您可以使用任何最便宜的降压稳压器,例如 LM 2596 和 12v 电源,可提供高达 3 Amp 的 5 V 稳压电源electronics.stackexchange.com/questions/174446/…
    【解决方案2】:

    也许不是您正在寻找的答案,但在嵌入式系统上使用 Python 和 OpenCV 并不是一个好主意。我在嵌入式系统上使用 python 时遇到了很多问题(即使使用 rasp 为您提供的强大硬件)。

    当我使用 C++ 而不是 Python 时,我遇到的所有性能问题都消失了。 C++ 上的 OpenCV 非常可靠,我强烈建议您尝试一下。

    【讨论】:

    • 无论如何我都会尝试运行您的代码。我目前没有树莓派可以试用,但我会尽快看看。
    • 好的,谢谢 Mathias 的提醒!我将尝试使其适应 Windows,看看我是如何开始的
    • 是的,我已经调整了我的程序以在我的 Windows 机器上运行,它运行没有任何问题。我认为问题出在@Doleron 指定的电源上。我目前正在手机充电器(5.0v,1,0A)上运行 Pi,所以我认为更换电源可能会解决这个问题。不过谢谢你的帮助。
    猜你喜欢
    • 2012-04-30
    • 2020-01-14
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多