主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

OpenCVのhaartrainingに使う、正解画像リストを作るのに役立つ道具を作った

                
tags:
 以前、画像からゾンビの顔を検出するものを作った。このときは技術的なところには全然詳しく触れなかった。
OpenCVを使ってちょっとおふざけをしてみた

 このゾンビの顔検出はOpenCVのhaartrainingというのを使っている。haartrainingとは、要は画像から検出したいターゲットがあるときに、ターゲットを含んだ画像と含んでいない画像を大量に与え、コンピュータに検出器を作らせてしまおうというものだ。最近のデジカメに入っている顔検出機能にhaartrainingは使われていたりするんだろう。詳しくは下記のサイトで学べる。
参考:http://gihyo.jp/dev/feature/01/opencv/0004

 リンク先を見ればわかるがこのhaartrainingをするとき、正解画像リストを作るのが面倒だ。画像を開いてターゲットの座標を確認したら、それをテキストファイルに打ち込んでいかなければならない。なので補助道具をPyGTKで作った。画像ビューアと座標入力の機能を両方とも備えている。ターゲットの座標はキーボードを叩かなくても、マウスのドラッグで入力できる。
120603_2.jpg


 というわけでGUIツールも入れたhaartrainingセットを置いておく。
 作成したツールは解凍後のフォルダ直下にHelpHaar.pyという名前で入れてある。pフォルダにターゲットを含む画像、nフォルダにターゲットを含まない画像を入れること。ツールのGUIにあるfinishボタンを押すとok.txtとng.txtをじぇねれーとする。上書き確認なく実行される点に留意。
https://skydrive.live.com/?cid=14d4b360c466b0c5#cid=14D4B360C466B0C5&id=14D4B360C466B0C5%21135

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import re
import glob

##import pygtk
##pygtk.require('2.0')
import gtk


XML = """<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="window1">
<property name="default_width">600</property>
<property name="default_height">250</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="yalign">0</property>
<property name="left_padding">12</property>
<child>
<object class="GtkEventBox" id="eventbox1">
<property name="visible">True</property>
<child>
<object class="GtkImage" id="image1">
<property name="width_request">500</property>
<property name="height_request">500</property>
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="yalign">0</property>
<property name="stock">gtk-missing-image</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;frame1&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox1">
<property name="width_request">191</property>
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<child>
<object class="GtkEntry" id="entry1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="entry2">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="invisible_char">&#x25CF;</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTextView" id="textview1">
<property name="height_request">140</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="label" translatable="yes">&lt;b&gt;frame2&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox3">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="button_back">
<property name="label" translatable="yes">&#x2190;</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_forward">
<property name="label" translatable="yes">&#x2192;</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="xalign">0.51999998092651367</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button_finish">
<property name="label" translatable="yes">finish</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
</object>
<packing>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>"""

class helpHaarTraining:
def __init__(self):
self.builder = gtk.Builder()
#sample.gladeファイルから画面を作成
self.builder.add_from_string(XML)
## self.builder.add_from_file(r'haar.glade')

#オブジェクトを取得、マウスイベントとコネクト
self.window = self.builder.get_object("window1")
self.window.connect("destroy", lambda w: gtk.main_quit())
self.window.show()
self.image = self.builder.get_object("image1")
self.ebox = self.builder.get_object("eventbox1")
self.ebox.connect("button-press-event", self.start_point)
self.ebox.connect("button-release-event", self.end_point)
self.button_back = self.builder.get_object("button_back")
self.button_back.connect("clicked", self.change_picture, -1)
self.button_forward = self.builder.get_object("button_forward")
self.button_forward.connect("clicked", self.change_picture, 1)
self.button_finish = self.builder.get_object("button_finish")
self.button_finish.connect("clicked", self.finish, -1)
self.textview = self.builder.get_object("textview1")
self.tbuffer=gtk.TextBuffer()
self.textview.set_buffer(self.tbuffer)

#初期設定
self.num_present_image = 0
self.change_picture(self.window ,0)
self.textdata = ""

#描画
self.window.show_all()

def store_haar_area(self):
"""画像ファイル名と目標物の座標をself.textdataにストア
"""
text = self.tbuffer.get_text(self.tbuffer.get_start_iter(),
self.tbuffer.get_end_iter())
li_rect = text.replace(',', '').replace('(', '').replace(')', '').split('\n')
li_rect = [nums for nums in li_rect if nums]
text_rect = "%s %s %s\n" %(self.img_filename, len(li_rect), " ".join(li_rect))
self.textdata += text_rect
print(text_rect)
self.tbuffer.set_text("")

def change_picture(self, widget, num):
"""表示画像を切り替える
"""
if self.tbuffer.get_text(self.tbuffer.get_start_iter(),
self.tbuffer.get_end_iter()):
self.store_haar_area()
images = glob.glob("p/*.png") + glob.glob("p/*.jpg")
if num == -1 and self.num_present_image == 0:
num_next_image = len(images) - 1
elif num == 1 and self.num_present_image == len(images) - 1:
num_next_image = 0
else:
num_next_image = self.num_present_image + num
filename = images[num_next_image]
pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
width = pixbuf.get_width()
height = pixbuf.get_height()
chouhen = width if width >= height else height
scale = 500.0 / chouhen
print width * scale
scaled_buf = pixbuf.scale_simple(int(width * scale), int(height * scale), gtk.gdk.INTERP_BILINEAR)
self.image.set_from_pixbuf(scaled_buf)
self.imgscale = scale
self.img_filename = filename
self.num_present_image = num_next_image
self.window.show_all()

def start_point(self, widget, event):
"""目標物を含む矩形領域の左上の座標を得る
"""
x, y, state = event.window.get_pointer()
x = int(x / self.imgscale)
y = int(y / self.imgscale)
self.x1 = x
self.y1 = y
text = self.tbuffer.get_text(self.tbuffer.get_start_iter(),
self.tbuffer.get_end_iter())
self.tbuffer.set_text(text + "(%s, %s), " %(x-1, y-1))

def end_point(self, widget, event):
"""目標物を含む矩形領域の右下の座標を得る
"""
x, y, state = event.window.get_pointer()
x = int(x / self.imgscale) - self.x1
y = int(y / self.imgscale) - self.y1
text = self.tbuffer.get_text(self.tbuffer.get_start_iter(),
self.tbuffer.get_end_iter())
self.tbuffer.set_text(text + "(%s, %s)\n" %(x-1, y-1))

def finish(self, widget, event):
"""ok.txtとng.txtを作る
"""
if self.tbuffer.get_text(self.tbuffer.get_start_iter(),
self.tbuffer.get_end_iter()):
self.store_haar_area()

images = glob.glob("p/*.png") + glob.glob("p/*.jpg")
textdata = self.textdata
for filename in images:
if not (filename in textdata):
pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
width = pixbuf.get_width() - 1
height = pixbuf.get_height() - 1
textdata += "%s 1 0 0 %s %s\n" %(filename, width, height)
with open("ok.txt", "w") as f:
f.write(textdata)

textdata = ""
images = glob.glob("n/*.png") + glob.glob("n/*.jpg")
for filename in images:
if not (filename in textdata):
textdata += "%s\n" %(filename)
with open("ng.txt", "w") as f:
f.write(textdata)

def main():
gtk.main()
return 0

if __name__ == "__main__":
helpHaarTraining()
main()
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。