質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

error: (-215:Assertion failed) src.cols > 0 && src.rows > 0 in function 'cv::warpAffine'

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,679

pythonでOpencvやdlibを使って顔を切り取るプログラムを作成しているのですが、下記プログラムの戻り値箇所でエラー起こってしまいます。
自分で調べても見ても解決方法が見つかりませんでした。画像のPathもあっています。

def fitting_rotated_image(img, angle):
    # 画像の縦、横のサイズを取得する
    height, width = img.shape[:2]
    # 画像の中心値を取得
    center = (int(width/2), int(height/2))
    # 度からラジアンに変換(deg to rad)
    radians = np.deg2rad(angle)
    # 回転の変換行列
    M = cv2.getRotationMatrix2D(center, angle, 1.0)

    new_width = int(abs(np.sin(radians) * height) + abs(np.cos(radians) * width))
    new_height = int(abs(np.sin(radians) * width) + abs(np.cos(radians) * height))

    M[0,2] += int((new_width-width)/2)
    M[1,2] += int((new_height-height)/2)

    # アファイン変換した画像を返す(ここでエラーが発生sa)
    return cv2.warpAffine(img, M, (new_width, new_height))
Traceback (most recent call last):
  File "dlib_face_cut.py", line 82, in <module>
    rotated_im = fitting_rotated_image(face_im, angle)
  File "dlib_face_cut.py", line 26, in fitting_rotated_image
    return cv2.warpAffine(img, M, (new_width, new_height))
cv2.error: OpenCV(4.2.0) C:\projects\opencv-python\opencv\modules\imgproc\src\imgwarp.cpp:2594: error: (-215:Assertion failed) src.cols > 0 && src.rows > 0 in function 'cv::warpAffine'


ディレクトリ内に10万枚近くの画像が入っているのですが、必ず1270枚目でエラーが出ます。(画像に不備があるのかと思い、1270枚目の画像を取り除き実行してみても結果は同じ)

理由がわかる方、教えていただけたら幸いです。宜しくお願い致します。

追加事項

programの全体を載せます。宜しくお願い致します。

import cv2
import numpy as np
import math
import dlib
import os
import glob
import time

def fitting_rotated_image(img, angle):
    # 画像の縦、横のサイズを取得する
    height, width = img.shape[:2]
    # 画像の中心値を取得
    center = (int(width/2), int(height/2))
    # 度からラジアンに変換(deg to rad)
    radians = np.deg2rad(angle)
    # 回転の変換行列
    M = cv2.getRotationMatrix2D(center, angle, 1.0)

    new_width = int(abs(np.sin(radians) * height) + abs(np.cos(radians) * width))
    new_height = int(abs(np.sin(radians) * width) + abs(np.cos(radians) * height))

    M[0,2] += int((new_width-width)/2)
    M[1,2] += int((new_height-height)/2)

    # アファイン変換した画像を返す
    return cv2.warpAffine(img, M, (new_width, new_height))

start = time.time()

# 顔の位置を取得する
detector = dlib.get_frontal_face_detector()
# 顔の68箇所の位置の座標を取得する
predictor = dlib.shape_predictor('./shape_predictor_68_face_landmarks.dat')

# ディレクトリ内の画像を指定
image_list = glob.glob('./~/*')
count = 1
pro_time = 0
# 新しいディレクトリを作成
os.makedirs('~', exist_ok = True)
# for文で一枚ずつ処理していく
for image in image_list:
    pro_start = time.time()
    pro_time += 1
    print("Processint Time :", pro_time)
    # 処理する画像を指定
    im = cv2.imread(image, cv2.IMREAD_COLOR)

    # 画像が見つからない場合
    if im is None:
        print("count:", count, '画像が見つかりません')
        #exit()
        continue

    rects = detector(im, 1)

    if len(rects) == 0:
        print("count:", count, '顔が抽出されませんでした')
        #exit()
        continue

    for index, rect in enumerate(rects):

        # 顔だけ切り出す
        rectWidth = rect.width()
        rectHeight = rect.height()
        rectCenter = rect.center()
        x_start = rectCenter.x - rectWidth
        x_end = x_start + rectWidth * 2
        y_start = rectCenter.y - rectHeight
        y_end = y_start + rectHeight * 2
        face_im = im[y_start:y_end, x_start:x_end]

        # 顔の角度を修正
        points = []
        for point in predictor(im, rect).parts():
            points.append([int(point.x), int(point.y)])

        x_diff = points[45][0] - points[36][0]
        y_diff = points[45][1] - points[36][1]
        angle = math.degrees(math.atan2(y_diff, x_diff))
        rotated_im = fitting_rotated_image(face_im, angle)

        # 回転後の画像で顔検出して画像保存
        rotated_rects = detector(rotated_im, 1)
        if len(rotated_rects) == 0:
            print("count:", count, '顔が抽出されませんでした')
            continue

        else:
            rotated_rect = rotated_rects[0]
            x_start = rotated_rect.left()
            x_end = rotated_rect.right()
            y_start = rotated_rect.top()
            y_end = rotated_rect.bottom()
            cropped_im = rotated_im[y_start:y_end, x_start:x_end]

            cv2.imwrite('./~.jpg'.format(count), cropped_im)
            pro_finish = time.time()

            print("count", count, "finish.")
            print("Processing Time:", pro_finish - pro_start, "sec")

            count += 1

    print("\n")

finish = time.time()

print("All Processing Time:", finish - start, "sec")
print(count, "face")
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • can110

    2020/07/29 20:46

    エラーが発生したのがglob.globした結果のリストから1270番目というわけではなく「1270.jpg」だと特定できていれば、それでよいです。

    キャンセル

  • yuki23

    2020/07/29 21:09

    ソースコードを見る限り、画像のファイル名を出力させたりはしていないようですが、どうやって 1270.jpg が原因だと判断しましたか? ということです
    glob の結果はファイル名でソートされているとは限らないので、count = 1270 だからといって 1270.jpg というファイル名とは限りません(そもそも、ファイル名がどのような規則でつけられているかも提示されていませんが)

    キャンセル

  • Tetsuya_Kosaka

    2020/07/29 21:14 編集

    >yuki23さん

    すみません。ここには載せていないのですがプログラムの48行目にprint("Processint Time :", pro_time, "File Name :", os.path.basename(image))を追加して試しています。
    そして分かったことなのですが、エラーになるのは1269.jpgでした。すみません。
    (画像のプロパティを調べてみても他の画像と変わったところはありませんでした。)

    ちなみに、45行目のfor文をfor image in natsorted(image_list):に変更してやってみましたが、変わりませんでした...。

    キャンセル

回答 1

0

やるべきことは

  • 1269.jpg を除いて実行してみる
    エラーがでなければ1269.jpgが原因の可能性が高い
    1269番目で同じくエラーとなればアルゴリズム側の原因の可能性が高い
    別の箇所で同じエラーとなれば蓄積した値がオーバーフローなどのアルゴリズム側の可能性が高い

  • 1269.jpgを別の名前にして(実施順を変えて)例えば
    1269.jpgを1200.jpgに、1200.jpgを1269.jpgで実行してみる

1200番目で同じエラーとなればやはりその画像が原因の可能性が高い
1269番目で同じエラーとなればアルゴリズム側の原因の可能性が高い

などと絞れると思います。
「画像のプロパティ」だけではわからないと思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る