はじめに
前回、Selective Searchを使ってステーキ定食の画像の物体検出を行いました。確かに精度は上がったものの、約50毎の画像の内、ゴミのような画像、同じ画像(若干切り抜き位置が違う)、必要な物体画像の約3種類に分類されていることに気づきました。今回は、その中から必要な物体画像のみを選別できないかをやってみようと思います。
仮説
画像から物体抽出する際にオーバラップの数が多い画像こそ必要な物体画像ではないか。と言いながらも、実は親子関係の矩形の子の部分を除けないかといったものです。
こいつは何を言っているんだ
ようするに画像から物体検出をする際に、矩形で抽出してますが、矩形同士が混ざりあった部分をオーバラップと呼んでいます。
下記の画像の赤い部分です。
参考元
- (たのしい当たり判定講座1 -矩形同士の当たり判定(初級編)-)[http://d.hatena.ne.jp/ono36/20070718/p1]
ソースコード
とりあえず書いてみました。
group_image
# -*- coding: utf-8 -*-
import cv2
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import selectivesearch
import os
def main():
# loading lena image
img = cv2.imread("{ステーキ定食画像}")
# perform selective search
img_lbl, regions = selectivesearch.selective_search(
img,
scale=500,
sigma=0.9,
min_size=10
)
candidates = set()
for r in regions:
# excluding same rectangle (with different segments)
if r['rect'] in candidates:
continue
# excluding regions smaller than 2000 pixels
if r['size'] < 2000:
continue
# distorted rects
x, y, w, h = r['rect']
if w / h > 1.2 or h / w > 1.2:
continue
candidates.add(r['rect'])
# draw rectangles on the original image
fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
ax.imshow(img)
overlaps = {}
# オーバーラップの数をカウントして配列に代入します。
for x, y, w, h in candidates:
group = '%s_%s_%s_%s' % (x, y, w, h)
for x2, y2, w2, h2 in candidates:
if x2 - w < x < x2 + w2 and y2 - h < y < y2 + h2:
if not group in overlaps:
overlaps[group] = 0
overlaps[group] = overlaps[group] + 1
print overlaps
# オーバーラップの数が30以上のファイルを出力します(30は勝手に閾値を敷いています)。
for key, overlap in enumerate(overlaps):
if overlap > 30:
for x, y, w, h in candidates:
group = x + y + w + h
if group in overlaps:
cv2.imwrite("{ディレクトリパス}" + str(group) + '.jpg', img[y:y + h, x:x + w])
補足
- 物体検出した画像とオーバーラップしているかどうかを判定します。
if x2 - w < x < x2 + w2 and y2 - h < y < y2 + h2:
- オーバーラップの数が30以上の抽出結果のみ画像として保存します。
結果
(元)50枚 → 36枚
ステーキ定食の画像の中で約3割くらい不要なものが除かれました。
また、前回の5種類の物体画像が5種類ともの残ってました。
まとめ
- 今回、検証画像が1種類なので少し調整と結果判定を寄せてますので、他の画像で試してみるとまた異なった結果になってくるかもしれません。
- 次回はクラスタリングちっくな事をできればと思ってます。