【问题标题】:how to make python perform a command after open cv detected a face?open cv检测到人脸后如何让python执行命令?
【发布时间】:2017-08-17 09:37:10
【问题描述】:

我正在建造一个机器人。我几乎所有的代码都是从其他人的教程项目中复制而来的。

我正在使用 Raspberry Pi 相机来检测面部,并且我有这个电动 Nerf 枪,我想在 opencv 检测到面部之后才可以开火。现在,无论是否检测到人脸,我的代码都会触发 Nerf 枪。请告诉我我做错了什么?我认为问题出在if len(faces) > 0 区域。这是我所有的代码。

程序 1,名为 cbcnn.py

​​>
import RPi.GPIO as gpio
import time

def init():
    gpio.setmode(gpio.BOARD)
    gpio.setup(22, gpio.OUT)

def fire(tf):
    init()
    gpio.output(22, True)
    time.sleep(tf)
    gpio.cleanup()

print 'fire'
fire(3)

程序 2,名为 cbfd2.py


import io
import picamera
import cv2
import numpy
from cbcnn import fire

#Create a memory stream so photos doesn't need to be saved in a file
stream = io.BytesIO()

#Get the picture (low resolution, so it should be quite fast)
#Here you can also specify other parameters (e.g.:rotate the image)
with picamera.PiCamera() as camera:
    camera.resolution = (320, 240)
    camera.vflip = True
    camera.capture(stream, format='jpeg')

#Convert the picture into a numpy array
buff = numpy.fromstring(stream.getvalue(), dtype=numpy.uint8)

#Now creates an OpenCV image
image = cv2.imdecode(buff, 1)

#Load a cascade file for detecting faces 
face_cascade = cv2.CascadeClassifier('/home/pi/cbot/faces.xml  /haarcascade_frontalface_default.xml')

#Convert to grayscale
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

#Look for faces in the image using the loaded cascade file
faces = face_cascade.detectMultiScale(gray, 1.1, 5)

print "Found "+str(len(faces))+" face(s)"

if len(faces) > 0:
    ("fire")

#Draw a rectangle around every found face
for (x,y,w,h) in faces:
    cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2)

#Save the result image
cv2.imwrite('result.jpg',image)

【问题讨论】:

  • 哦,不。你不会因为我非常希望一个 nerf 瞄准机器人成为存在的东西而逃避一个离题的问题。请看How to Askminimal reproducible example
  • 我不明白我在帖子中做错了什么?请澄清。
  • 不。你读过链接吗?这里没有具体的编程问题,也没有办法复制错误,甚至无法说明具体错误是什么(“不拍人脸”虽然很搞笑,但不是正确的错误跟踪。)
  • @Ironchop 阅读了 Daniel 提供的 MCVE 链接。这个想法是,如果您有问题,请不要给我们很多可能与问题相关或无关的无用信息。首先,发现faces 包含的内容。然后以此为起点提问。据推测,我们不需要所有 PiCamera 的东西或 CV 堆栈。
  • 哦。我认为这个网站的全部目的是解决编程问题。我想我不明白这个网站的目的。

标签: python opencv numpy raspberry-pi3 robotics


【解决方案1】:

它触发是因为在您定义 fire(tf) 函数之后立即有一个 fire(3)。下面的命令只创建一个具有 1 个字符串值的元组:("fire")。它不会调用 fire 函数。

if len(faces) > 0:
    ("fire")

如果您只想在检测到人脸时触发,请将 fire(3) 移动到此 IF 下方并从顶部移除。

顺便说一句,您在这里导入了另一个东西:from cbcnn import fire 与您的函数同名。这将覆盖您的函数名称,如果您将 fire(3) 放在导入行下方,它可能会引发错误。要么将您的触发功能 fire(tf) 更改为 fire_rocket(tf),并将您的 fire(3) 更改为 IF 下的 fire_rocket(3)

或者将其添加到您的导入行(实际上您甚至没有使用!),您可以保持您的火函数名称原样:

from cbcnn import fire as Fire

问题更改后编辑:
修复我上面提到的 IF 并将火(一些数字)放在那里。
它触发的原因是当您从另一个程序导入某些内容时,它会运行整个脚本。因为 fire(3) 在那里,它会在您导入时自动调用该函数。
为避免这种情况,您必须:

  • 从您的 cbcnn.py 中删除其他部分:printfire(3)

或者

  • 将这些部分放在此 IF 语句中,以便仅在您自己实际运行 cbcnn.py 时运行它们,而不是通过导入它:

    if __name__=='__main__':
        print(fire)
        fire(3)
    

【讨论】:

  • 对不起,我没有澄清我在这里发布了两个脚本。第一个被称为 cbcnn.py “c-bot cannon”。 cbcnn.py 脚本着火结束 (3)。之后是第二个脚本 cbfd2.py “c-bot face detection 2”。这就是为什么,在第二部分,我“从 cbcnn 导入火”。
  • 我刚刚编辑了我的问题,以便现在更容易看出这是两个单独的脚本
【解决方案2】:

我已经在另一篇文章中回答了你,但是,你在哪里:

cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2)

在那里你可以放任何你想要的东西,如果你进入for循环,这意味着你已经检测到了一张脸。正如您在发布的代码中看到的那样,在这种情况下,它们会绘制一个矩形,但您可以在那里做任何事情,x、y、w 和 h 会为您提供检测到的人脸的坐标和大小。

【讨论】:

  • 我必须仔细阅读你的答案,很多次才能理解你试图向我解释的内容。我非常感谢你们两个,他们查看了我的脚本并花时间向我解释我做错了什么。让我告诉你,我第一次登录这里的时候很不高兴,问我的问题,只受到批评和消极的欢迎。我刚刚让它按照我想要的方式工作。没有你们,我是想不通的。再来一次。非常感谢你。我会尽快发布解决方案。
【解决方案3】:
import io
import picamera
import cv2
import numpy
import RPi.GPIO as gpio
import time

#Create a memory stream so photos doesn't need to be saved in a file
stream = io.BytesIO()

#Get the picture (low resolution, so it should be quite fast)
#Here you can also specify other parameters (e.g.:rotate the image)
with picamera.PiCamera() as camera:
    camera.resolution = (320, 240)
    camera.vflip = True
    camera.capture(stream, format='jpeg')

#Convert the picture into a numpy array
buff = numpy.fromstring(stream.getvalue(), dtype=numpy.uint8)

#Now creates an OpenCV image
image = cv2.imdecode(buff, 1)

#Load a cascade file for detecting faces
face_cascade =    cv2.CascadeClassifier('/home/pi/cbot/faces.xml/haarcascade_frontalface_default.xml')

#Convert to grayscale
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

#Look for faces in the image using the loaded cascade file
faces = face_cascade.detectMultiScale(gray, 1.1, 5)

print "Found "+str(len(faces))+" face(s)"

#Draw a rectangle around every found face
for (x,y,w,h) in faces:
    cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2)

    def init():
        gpio.setmode(gpio.BOARD)
        gpio.setup(22, gpio.OUT)

    def fire(tf):
        init()
        gpio.output(22, True)
        time.sleep(tf)
        gpio.cleanup()

    print 'fire'
    fire(3)


#Save the result image
cv2.imwrite('result.jpg',image)

【讨论】:

  • 由于从单独的程序中导入“fire”命令会导致问题,我只是将较小的程序集成到较大的程序中。我把所有“fire”程序的东西都放在“for”的东西下。
  • 这是错误的做法......你不应该在 for 循环中定义函数。您只需要定义一次(通常是在导入之后)。你可以在 for 循环中调用你的函数(就像你对 fire(3) 所做的那样)。现在关于在那个 for 循环中调用 fire(3) ......如果框架中有 5 个人,就这样。它会调用火,然后休眠 3 秒并执行相同操作,直到它开火 5 次。这可能不是您想要的,因为当它触发下一个镜头时,帧应该已经改变,这些人甚至可能不在其他帧中。你最好使用if len(faces)>0
  • 啊,是的。我明白你在说什么。我应该将我的定义移到顶部,在我的导入下方。但是这种方式,实际上工作得很好。我会把“if len(faces)>0”放在 cv2.rectangle(image.......ect. 的正下方吗?
  • 再一次,我非常感谢你花时间看我的剧本,并给我建议。我对编程知之甚少。
  • 在 for 循环中定义函数只会让你的程序变慢(因为它只是在每次循环运行时运行不必要的代码)。它仍然可以工作,但这是完全错误的。您可以将 if 放在 for 循环之前或之后(没关系)。
猜你喜欢
  • 2014-08-26
  • 1970-01-01
  • 2013-12-22
  • 2021-06-30
  • 2015-07-15
  • 2018-02-22
  • 2016-07-28
  • 1970-01-01
  • 2013-09-24
相关资源
最近更新 更多