Symfoware

Symfowareについての考察blog

OpenCV 写真に特定の人物が写っているか判定 その2

OpenCVで顔画像の判定を行ってみました。
OpenCV を使用して、写真に特定の人物が写っているか判定する


精度が悪いので、どうやったら精度が上がるか考えてみます。


戦いは数だよアニキ



比較用の画像を増やしてみます。

496_01.png


  1. # -*- coding:utf-8 -*-
  2. import numpy
  3. import cv2
  4. def calc(detector_name, extractor_name, matcher_name, face_image):
  5.     
  6.     # キーポイントの検出
  7.     detector = cv2.FeatureDetector_create(detector_name)
  8.     keypoints1 = detector.detect(face_image)
  9.     # 画像データの特徴量
  10.     descripter = cv2.DescriptorExtractor_create(extractor_name)
  11.     k1,d1 = descripter.compute(face_image, keypoints1)
  12.     # matcher準備
  13.     matcher = cv2.DescriptorMatcher_create(matcher_name)
  14.     
  15.     min_dist = 100000
  16.     
  17.     # テスト画像読み込み
  18.     for i in xrange(1, 33):
  19.         
  20.         # 画像はグレースケール変換済
  21.         test_file = "okawa_gray/face_%02d.jpg" % i
  22.         test_image = cv2.imread(test_file)
  23.         
  24.         #print test_file
  25.         
  26.         # キーポイントの検出
  27.         keypoints2 = detector.detect(test_image)
  28.         #print len(keypoints2)
  29.         k2,d2 = descripter.compute(test_image, keypoints2)
  30.         # キーの一致度合いを調べる
  31.         try:
  32.             matches = matcher.match(d1, d2)
  33.         except:
  34.             continue
  35.         #print '#matches:', len(matches)
  36.         dist = [m.distance for m in matches]
  37.         
  38.         if len(dist) == 0:
  39.             continue
  40.         
  41.         min_dist = min(min(dist), min_dist)
  42.     
  43.     return min_dist
  44.     
  45. cascade_path = '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml'
  46. for i in xrange(1, 11):
  47.     filename = 'test/pic%d.jpg' % i
  48.     #ファイル読み込み
  49.     image = cv2.imread(filename)
  50.     #グレースケール変換
  51.     image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
  52.     #カスケード分類器の特徴量を取得する
  53.     cascade = cv2.CascadeClassifier(cascade_path)
  54.     #物体認識(顔認識)の実行
  55.     facerect = cascade.detectMultiScale(
  56.                     image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
  57.     if len(facerect) <= 0:
  58.         print u'not found!'
  59.     # 適当に一番大きそな画像を探す
  60.     rect = facerect[0]
  61.     for r in facerect:
  62.         if rect[2] < r[2]:
  63.             rect = r
  64.         
  65.     x = rect[0]
  66.     y = rect[1]
  67.     w = rect[2]
  68.     h = rect[3]
  69.     # img[y: y + h, x: x + w]
  70.     face_image = image_gray[y:y+h, x:x+w]
  71.     cv2.imwrite("detected_" + filename, face_image)
  72.     resutl = calc('Dense', 'BRISK', 'BruteForce-Hamming', face_image)
  73.     if resutl < 100:
  74.         print filename, resutl, 'okawa'
  75.     else:
  76.         print filename, resutl, 'not okawa'




テストした画像はこちら。

496_02.png



○:test/pic1.jpg 97.0 okawa
○:test/pic2.jpg 108.0 not okawa
○:test/pic3.jpg 99.0 okawa
○:test/pic4.jpg 68.0 okawa
○:test/pic5.jpg 79.0 okawa
×:test/pic6.jpg 92.0 okawa
○:test/pic7.jpg 102.0 not okawa
×:test/pic8.jpg 102.0 not okawa
○:test/pic9.jpg 108.0 not okawa
×:test/pic10.jpg 106.0 not okawa



精度変わらず。





上位TOP3の距離の平均



distanceの最小ではなく、TOP3の平均で比較してみます。


  1. # -*- coding:utf-8 -*-
  2. import numpy
  3. import cv2
  4. def calc(detector_name, extractor_name, matcher_name, face_image):
  5.     
  6.     # キーポイントの検出
  7.     detector = cv2.FeatureDetector_create(detector_name)
  8.     keypoints1 = detector.detect(face_image)
  9.     # 画像データの特徴量
  10.     descripter = cv2.DescriptorExtractor_create(extractor_name)
  11.     k1,d1 = descripter.compute(face_image, keypoints1)
  12.     # matcher準備
  13.     matcher = cv2.DescriptorMatcher_create(matcher_name)
  14.     
  15.     min_dist = 100000
  16.     
  17.     # テスト画像読み込み
  18.     for i in xrange(1, 33):
  19.         
  20.         # 画像はグレースケール変換済
  21.         test_file = "okawa_gray/face_%02d.jpg" % i
  22.         test_image = cv2.imread(test_file)
  23.         
  24.         #print test_file
  25.         
  26.         # キーポイントの検出
  27.         keypoints2 = detector.detect(test_image)
  28.         #print len(keypoints2)
  29.         k2,d2 = descripter.compute(test_image, keypoints2)
  30.         # キーの一致度合いを調べる
  31.         try:
  32.             matches = matcher.match(d1, d2)
  33.         except:
  34.             continue
  35.         #print '#matches:', len(matches)
  36.         dist = [m.distance for m in matches]
  37.         
  38.         if len(dist) < 3:
  39.             continue
  40.         
  41.         sorted_dist = sorted(dist)
  42.         
  43.         top3_min_dist = 0
  44.         for j in xrange(0, 3):
  45.             top3_min_dist += sorted_dist[j]
  46.         
  47.         min_dist = min(top3_min_dist / 3, min_dist)
  48.     
  49.     return min_dist
  50.     
  51. cascade_path = '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml'
  52. for i in xrange(1, 11):
  53.     filename = 'test/pic%d.jpg' % i
  54.     #ファイル読み込み
  55.     image = cv2.imread(filename)
  56.     #グレースケール変換
  57.     image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
  58.     #カスケード分類器の特徴量を取得する
  59.     cascade = cv2.CascadeClassifier(cascade_path)
  60.     #物体認識(顔認識)の実行
  61.     facerect = cascade.detectMultiScale(
  62.                     image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
  63.     if len(facerect) <= 0:
  64.         print u'not found!'
  65.     # 適当に一番大きそな画像を探す
  66.     rect = facerect[0]
  67.     for r in facerect:
  68.         if rect[2] < r[2]:
  69.             rect = r
  70.         
  71.     x = rect[0]
  72.     y = rect[1]
  73.     w = rect[2]
  74.     h = rect[3]
  75.     # img[y: y + h, x: x + w]
  76.     face_image = image_gray[y:y+h, x:x+w]
  77.     cv2.imwrite("detected_" + filename, face_image)
  78.     
  79.     resutl = calc('Dense', 'BRISK', 'BruteForce-Hamming', face_image)
  80.     
  81.     
  82.     if resutl < 100:
  83.         print filename, resutl, 'okawa'
  84.     else:
  85.         print filename, resutl, 'not okawa'




×:test/pic1.jpg 111.333333333 not okawa
○:test/pic2.jpg 117.0 not okawa
×:test/pic3.jpg 107.333333333 not okawa
○:test/pic4.jpg 85.0 okawa
○:test/pic5.jpg 90.3333333333 okawa
○:test/pic6.jpg 102.0 not okawa
○:test/pic7.jpg 106.666666667 not okawa
×:test/pic8.jpg 108.0 not okawa
○:test/pic9.jpg 114.666666667 not okawa
×:test/pic10.jpg 111.333333333 not okawa




精度は落ちましたが、今までOKと間違えていた写真を弾けるようになりました。
大川が写っていると判定した写真に限ると正解率100%です。





他のアルゴリズムとの組み合わせ



2つのアルゴリズムでチェックしてみます。
いずれかが適当に決めたしきい値を下回ればOKと判定してみました。


  1. # -*- coding:utf-8 -*-
  2. import numpy
  3. import cv2
  4. def calc(detector_name, extractor_name, matcher_name, face_image):
  5.     
  6.     # キーポイントの検出
  7.     detector = cv2.FeatureDetector_create(detector_name)
  8.     keypoints1 = detector.detect(face_image)
  9.     # 画像データの特徴量
  10.     descripter = cv2.DescriptorExtractor_create(extractor_name)
  11.     k1,d1 = descripter.compute(face_image, keypoints1)
  12.     # matcher準備
  13.     matcher = cv2.DescriptorMatcher_create(matcher_name)
  14.     
  15.     min_dist = 100000
  16.     
  17.     # テスト画像読み込み
  18.     for i in xrange(1, 33):
  19.         
  20.         # 画像はグレースケール変換済
  21.         test_file = "okawa_gray/face_%02d.jpg" % i
  22.         test_image = cv2.imread(test_file)
  23.         
  24.         #print test_file
  25.         
  26.         # キーポイントの検出
  27.         keypoints2 = detector.detect(test_image)
  28.         #print len(keypoints2)
  29.         k2,d2 = descripter.compute(test_image, keypoints2)
  30.         # キーの一致度合いを調べる
  31.         try:
  32.             matches = matcher.match(d1, d2)
  33.         except:
  34.             continue
  35.         #print '#matches:', len(matches)
  36.         dist = [m.distance for m in matches]
  37.         
  38.         if len(dist) < 3:
  39.             continue
  40.         
  41.         sorted_dist = sorted(dist)
  42.         
  43.         top3_min_dist = 0
  44.         for j in xrange(0, 3):
  45.             top3_min_dist += sorted_dist[j]
  46.         
  47.         min_dist = min(top3_min_dist / 3, min_dist)
  48.     
  49.     return min_dist
  50.     
  51. cascade_path = '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml'
  52. for i in xrange(1, 11):
  53.     filename = 'test/pic%d.jpg' % i
  54.     #ファイル読み込み
  55.     image = cv2.imread(filename)
  56.     #グレースケール変換
  57.     image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
  58.     #カスケード分類器の特徴量を取得する
  59.     cascade = cv2.CascadeClassifier(cascade_path)
  60.     #物体認識(顔認識)の実行
  61.     facerect = cascade.detectMultiScale(
  62.                     image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
  63.     if len(facerect) <= 0:
  64.         print u'not found!'
  65.     # 適当に一番大きそな画像を探す
  66.     rect = facerect[0]
  67.     for r in facerect:
  68.         if rect[2] < r[2]:
  69.             rect = r
  70.         
  71.     x = rect[0]
  72.     y = rect[1]
  73.     w = rect[2]
  74.     h = rect[3]
  75.     # img[y: y + h, x: x + w]
  76.     face_image = image_gray[y:y+h, x:x+w]
  77.     cv2.imwrite("detected_" + filename, face_image)
  78.     
  79.     resutl = calc('Dense', 'BRISK', 'BruteForce-Hamming', face_image)
  80.     resutl2 = calc('BRISK', 'BRISK', 'BruteForce-Hamming', face_image)
  81.     
  82.     if (resutl < 100) or (resutl2 < 50):
  83.         print filename, resutl, resutl2, 'okawa'
  84.     else:
  85.         print filename, resutl, resutl2, 'not okawa'




×:test/pic1.jpg 111.333333333 101.0 not okawa
○:test/pic2.jpg 117.0 88.6666666667 not okawa
×:test/pic3.jpg 107.333333333 90.6666666667 not okawa
○:test/pic4.jpg 85.0 108.666666667 okawa
○:test/pic5.jpg 90.3333333333 50.3333333333 okawa
○:test/pic6.jpg 102.0 75.0 not okawa
○:test/pic7.jpg 106.666666667 102.666666667 not okawa
○:test/pic8.jpg 108.0 26.6666666667 okawa
○:test/pic9.jpg 114.666666667 84.0 not okawa
○:test/pic10.jpg 111.333333333 6.66666666667 okawa




正解率が上がりました。

画像認識、奥が深いです。
他にもパラメーターチューニングなど工夫の余地は残されていると思います。

関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2014/11/03(月) 12:39:20|
  2. Python
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<FreeBSD 10 + Pythonで「UnicodeEncodeError: 'ascii' codec can't encode characters」 | ホーム | OpenCV を使用して、写真に特定の人物が写っているか判定する>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1526-4ce15333
この記事にトラックバックする(FC2ブログユーザー)