現在Python, openCVを用いて顔検出のプログラムを作成しています。
cascade = cv2.CascadeClassifier(cascade_path) facerect = cascade.detectMultiScale(frame,scaleFactor=1.1,minNeighbors=1,minSize=(100,100)) if len(facerect) > 0: for rect in facerect: 処理
このようなコードを実行しようとした際に、len(facerect)が0になってしまいif内の処理を実行できません。
検出した顔を四角で囲むという処理は通っているので、顔の検出自体はできているはずなのですが...
また、dlibについても
dets = detector(frame[:, :, ::-1]) if len(dets) > 0: 処理
このコードについても同じ問題が発生しています。
そこで質問です。
顔を認識できているのにlen(facerect)やlen(dets)が0となる理由と解決策をご教示いただきたいです。
追記:今回使用したプログラム全体です。(動画をフレーム分割し、各画像から顔を検出,顔を囲んだ画像を保存という流れです)
import glob import cv2 import os import dlib import csv import matplotlib.pyplot as plt import numpy as np from PIL import Image, ImageDraw %matplotlib inline import pandas as pd from pandas import DataFrame, Series count=0 movie='パス.mov'#使用する動画 cap = cv2.VideoCapture(movie) while True: ret, img = cap.read() if ret == True: count += 1 cv2.imwrite('パス' + "Sample" + '_' + str("{0:05d}".format(count)) +'.jpg', img) #画像として保存する else: break files = sorted(glob.glob(r"パス/*.jpg") )# .jpgを整理する cascade = cv2.CascadeClassifier("パスhaarcascade_frontalface_default.xml") facerect = cascade.detectMultiScale(img,minSize=(100,100)) count=0 if len(facerect) > 0: for f in files: count += 1 img = cv2.imread(f) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = cascade.detectMultiScale(gray, minSize=(100, 100)) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] cv2.imwrite('パス' + "Sample_after" + '_' + str("{0:05d}".format(count)) +'.jpg', img) #画像として保存する cv2.waitKey(0) cv2.destroyAllWindows()
> len(facerect)が0になってしまいif内の処理を実行できません。
>検出した顔を四角で囲むという処理は通っている
facerectは何を表しているのでしょうか。コード中の「処理」は、何をしているのでしょうか。
この「処理」で、検出した顔を囲むのでは?違うのなら、「検出した顔を囲む」為に、どの変数を元に処理しているのでしょうか?
・コード全体を貼ってください
・ある画像では検出できるのに、ある画像だと検出できないということであれば、単に今の検出器の性能では、検出できなかったという話になります
facerectはcascade.detectMultiScale()にて検出した顔のリストです。
また検出した顔を囲むというのは、本当に顔が検出されているかを確認するために実行しただけで、本来は別の処理を行う予定です。
試験用に作成した「検出した顔を囲む」コードを質問に追記いたします。
以下の2つはなぜ必要なのでしょうか?img に入っているのは最後に取得した動画のフレームなので、そこに顔が写っていない (または写っているけど検出できなかった) 場合は if 文は False になると思うのですが。
facerect = cascade.detectMultiScale(img,minSize=(100,100))
と
if len(facerect) > 0:
iPhoneで見ているので間違っているかもですが。
while true と cascade = のインデントが同じなので、顔検出するのは一番最後のフレームか、画像がない(おそらく空の)情報ですよね?
ここのインデントが正しくて、毎フレーム検出しているとしても、「if len(facerect) > 0:」が正の時に実行されるブロックの中に顔に四角を描くロジックが入っているので、「len(facerect)が0になってしまいif内の処理を実行できません。
検出した顔を四角で囲むという処理は通っている」ということにはならないと思うのですが?
最後に取得した画像にも顔は検出されていました。
また、その2文はこの顔を囲むプログラムには必要のないものですが、本来私の作成したいプログラム(卒論のためのもの)に必要な文章です。
補足ではありますが、ややこしいので質問の流れを書かせていただきます
①元々卒論のためにプログラムを作成
②そのなかで、検出されていることの確認のために「if len(facerect) > 0:」が必要だが,値が0となりif内の処理が実行されない
③len(facerect) = 0となるのは顔が検出されていないときだとネットで発見
④顔が検出されているのかを確認するためにこのプログラムを作成して確かめた
⑤顔は検出され,死角でも囲われているのにlen(facerect) = 0となる理由がわからない,質問
22:25のコメントから、プログラムが2本あると推測します。①と④です。
この推測が正しいなら、④が描いているのは①が「検出なし」とした時と違う画像と考えられます。
プログラムは、書いた意図どおりには動きません。書いてある通りに動きます。意図と書いてあることが違う時、「バグ」と言われます。まずは、2つあると思われるプログラムの、意図と実際が一致しているかを確認することを勧めます。
ちなみに、追加されたコードは動きません。capがコメントアウトされています。本当に、意図と書いてあることが一致しているか、確認することを強く勧めます。
回答1件
あなたの回答
tips
プレビュー