콘텐츠로 바로가기

now0930 일지

이런저런 생각

  • 홈
  • 비공개
  • 강좌
  • 잔여 작업 조회
  • 위치

openface로 얼굴 판별

휴대폰으로 사진을 열심히 모았지만, 너무 많아 태그를 입력할 엄두가 나지 않았다. 입력할 때 파일의 정보를 추출하여 데이터 베이스에 정리했다. 언젠가 얼굴을 인식하는 소프트웨어를 응용하여 판별하려고 했는데, 2016년 정도에 개발된 openface를 찾았고 이를 사용하기로 했다. 인터넷의 누군가 좋은 튜토리얼을 (영문)만들었고 이를 많이 참조했다. 또한 openface가 수정없이 그대로 사용할 정도의 완성도를 보여준다. docker 이미지로 제공되는데 바로 사용할 수 있다.

목표한 4명의 얼굴을 학습시켰고, 이 모델을 기반으로 모든 파일을 분류 했다. 모델을 만들기는 금방인데, 사진에서 얼굴찾기, 그 얼굴이 누구인지는 확인하기 위해서는 많은 시간(내가 가진 PC로 3일..)을 썼다. 얼굴 인식 후 이를 파일로 기록하였고 아래와 같다.

=== /root/picture/사진/20150211_202325.jpg ===

=== /root/picture/사진/MyPhoto_0149.jpg ===
Predict Daewon @ x=2075 with 0.66 confidence.

=== /root/picture/사진/20140412_162452.jpg ===
List of faces in image from left to right
Predict Minsu @ x=1377 with 0.63 confidence.
Predict Daewon @ x=1549 with 0.86 confidence.
Predict Minsu @ x=1780 with 0.60 confidence.
Predict Daewon @ x=1893 with 1.00 confidence.

=== /root/picture/사진/20130219_152444.jpg ===
Predict Daewon @ x=63 with 0.52 confidence.

=== /root/picture/사진/20121208_110821.jpg ===

=== /root/picture/사진/사진110702_003.jpg ===

=== /root/picture/사진/사진120207_010.jpg ===
Predict Minsu @ x=732 with 0.59 confidence.

=== /root/picture/사진/20140405_160811.jpg ===
Predict Miae @ x=1288 with 0.99 confidence.

=== /root/picture/사진/20140406_085437_ShearesAve.jpg ===
Predict Daewon @ x=775 with 0.98 confidence.

=== /root/picture/사진/20131013_134752_과천동.jpg ===

가끔 한 파일에 여러 이름을 기록하는데, 아마 학습하지 않은 인물이 사진에 있기 때문이다. 신뢰도 0.8 미만이면 믿을 수 없다고 판단하여 지웠다. 공백을 지우고, 여러 행을 한 행으로 만들기 위해 다음 python 스크립을 사용 했다. sed를 사용하려 했으나, python이 낫다. docker로 디렉토리를 root 아래에 바로 마운트하여 경로에 root가 포함되었다. vim으로 해당 경로로 모두 변경했다. 데이터베이스에 굳이 신뢰도와 얼굴 위치를 넣지 않아도 되어 모두 지웠다.

#_*_ coding: utf-8 _*_
import re
import sys 
from signal import signal, SIGPIPE, SIG_DFL

signal(SIGPIPE,SIG_DFL)
result_file = open('./resultv3.txt','r')
flag_found_path=False;
flag_found_prediction=False;

num_lines = sum(1 for line in open('./resultv3.txt'))

for x in range(num_lines):
    context=result_file.readline()
    #path를 찾는부분.
    path = re.compile("=== .* ===")
    searched_path = path.search(context)

    #predict를 찾는 부분
    prediction = re.compile("Predict.*")
    searched_prediction = prediction.search(context)

    #===로 시작하는 부분. 
    if searched_path != None:
        flag_found_path=True

        #간단한 버전.
        path_str = searched_path.group()
        print('\n'+path_str,end=',')

    if searched_prediction != None:

        predict_str = searched_prediction.group()
        print(predict_str,end=',')

대부분 코드를 stack overflow에서 찾아 사용했다.

아래와 같은 “파일 경로” 대 “사람 이름”을 만들 수 있다.

/imageOtherPar/사진/20130225_163915.jpg,미애
/imageOtherPar/사진/20121224_203050.jpg,채윤
/imageotherpar/사진/20130926_151133_人大会堂西路.jpg,채윤
/imageotherpar/사진/20130926_151133_人大会堂西路.jpg,대원
/imageOtherPar/사진/사진110612_018.jpg,민수
/imageOtherPar/사진/사진110612_018.jpg,대원
/imageOtherPar/사진/20130128_212312.jpg,민수
/imageOtherPar/사진/사진110612_004.jpg,민수
/imageOtherPar/사진/20150331_131747.jpg,미애
/imageOtherPar/사진/20150505_142947.jpg,민수
/imageOtherPar/사진/20150505_141543.jpg,대원
/imageOtherPar/사진/20140405_160859.jpg,미애
/imageOtherPar/사진/사진111016_021.jpg,미애

이 파일을 별도 테이블을 만들어 굳이 python으로 mysql에 입력했다.

#_*_ coding: utf-8 _*_
import pymysql
import re
import sys 
import datetime
from signal import signal, SIGPIPE, SIG_DFL

#pipe를 사용하기 위해.
signal(SIGPIPE,SIG_DFL)



present = datetime.datetime.now()

print(present.date())

conn = pymysql.connect(host='localhost', user='*****', password='*****',
        db='*****', charset='utf8')

#column을 접근하기 위해 Dictionary cursor 사용
#curs = conn.cursor(pymysql.cursors.DictCursor)
curs = conn.cursor()


#read path from file

result_file = open('./찾을수있는얼굴v3.txt','r')

num_lines = sum(1 for line in open('./찾을수있는얼굴v3.txt'))


#이름을 ID로 변경.
#민수-2, 미애-9, 대원-10, 채윤-6


for x in range(num_lines):
    #한 줄을 읽음.
    context=result_file.readline()

    #경로 찾음.
    path = re.compile("\/.*jpg")
    searched_path = path.search(context)


    #tag 확인.
    #tag_from_file = re.compile("민수|대원|미애|채윤")
    tag_from_file = re.compile("jpg,.*$")
    tag_searched_from_file_tmp = tag_from_file.search(context)

    if tag_searched_from_file_tmp != None:
        #print(tag_searched_from_file_tmp.group())
        tmp_start = tag_searched_from_file_tmp.start()
        tmp_end = tag_searched_from_file_tmp.end()

        #file에서 찾은 태그.
        tag_searched_from_file = context[tmp_start+4:tmp_end]
        print(tag_searched_from_file)
        #print(type(tag_searched_from_file))


    if searched_path != None:
        found_path = searched_path.group()
        print(found_path)

    #sql = "select '" + found_path + "' from picture"
    sql = "select * from `picture` where `경로`='"+found_path+"' order by id desc"
    #sql = "insert into `id_with_photo_path`(`id`,`경로`) values (22,'test2/');"

    no_tag = 0
    if tag_searched_from_file == "민수" :
        no_tag = 2
    if tag_searched_from_file == "채윤" :
        no_tag = 6
    if tag_searched_from_file == "미애" :
        no_tag = 9
    if tag_searched_from_file == "대원" :
        no_tag = 10

    print(type(no_tag))
    print(found_path)

    sql = "insert into `id_with_photo_path`(`id`,`경로`,`updated`) values ('"+str(no_tag)+"','"+found_path+"','"+str(present.year)+"-"+str(present.month)+"-"+str(present.day)+"');"
    #sql = """ insert into `id_with_photo_path`(`id`,`경로`) values (%s, %s)"""


    print(sql)


    #print("sql is", sql)
    curs.execute(sql)

    #rows = curs.fetchall()

    #rows는 전체 행을 표시.
    #column을 뽑기 위해 루프로 돌림.

    #for row in rows:

        #print(type(rows))
        #print(len(rows))
    #    tag=row["태그"]


        #태그 확인부분.
        #print(tag)
        #rows.strip(",").split(",")


#conn.commit()


conn.close()

마지막에 conn.commit()을 하지 않으면 sql로 insert를 할 수 없다. 두번 실행을 방지하기 위해 #conn.commit()로 주석처리 했다.

다음으로 홈페이지에서 파일을 관리하기 위해, 기존에 작성한 사진 조회 페이지를 수정했다. php를 잘 알면 더 고급지게 할 수 있겠으나, 딱 이정도 수준이면 충분하다.

<?php /* Template Name: myPhotoQuery*/ ?>
<?php
get_header(); ?>

<div id="main-content" class="main-content">

<?php
	if ( is_front_page() && twentyfourteen_has_featured_posts() ) {
		// Include the featured content template.
		get_template_part( 'featured-content' );

	}
?>
	<div id="primary" class="content-area">
		<div id="content" class="site-content" role="main">
			<?php
				// Start the Loop.
				while ( have_posts() ) : the_post();

					// Include the page content template.
					get_template_part( 'content', 'page' );


					// If comments are open or we have at least one comment, load up the comment template.
					if ( comments_open() || get_comments_number() ) {
						comments_template();
					}
				endwhile;
			?>

<?php
//로그인 되었는지  확인하는 부분..
if( is_user_logged_in())
{
	echo '환영합니다.';
	?>
<html>
<body>
<?php
	$config = parse_ini_file("****"); 

	$link = mysqli_connect('localhost',$config['user'],$config['passwd']);

	
	if(!$link)
	{
		echo 'Could not connect';
		echo '<br />';
		exit;
	}
	else
	{
		echo '<br />';
		echo 'Connected<br />';
		echo '<br />';
	}

	mysqli_set_charset($link,"utf8");
	if(!mysqli_select_db($link,'myHome')){
		echo "could not select DB<br />";}
	else{
		echo "data base selected<br />";}
	

	//한국 시각 기준으로 설정..
	date_default_timezone_set("Asia/Seoul");
	$today = date("Y-m-d");
	$time = time();
	#echo $time;
	$minus30Day = date("Y-m-d", strtotime("-30 day", $time));
	#echo $today;
	#echo $targetDay;


	//처음 접속시 사용자가 입력하는 부분..
?>
	<form method="POST" action="" name="날자 입력">
	<br><hr>
	시작 날자
	<input value=" <?php echo $minus30Day ?>" name="InputStartDay" type="datetime-local" >
	끝 날자
	<input value=" <?php echo $today?>" name="InputEndDay" type="datetime-local">
	<br><br>
	사람 이름<br>
	<input value="" name="InputTag"><br>
	<br><br>
	표식 개수<br>
	<input value="10" name="InputLimit" type="number" min="1" max="200">
	<br><br>
	
	선택 완료
	<input name="submitSelect" type="submit">

	</form>

<?php
	//선택후 쿼리로 전송..
	if(isset($_POST["submitSelect"])){

		#InputTag가 누구를 가리키는지 확인.
		$numbered_person = 0;
		if ($_POST[InputTag] == '대원') $numbered_person = 10;
		if ($_POST[InputTag] == '미애') $numbered_person = 9;
		if ($_POST[InputTag] == '민수') $numbered_person = 2;
		if ($_POST[InputTag] == '채윤') $numbered_person = 6;


		$file_limiter = 50;
		if( $_POST[InputLimit] > 0 and $_POST[InputLimit] < 1000)
			$file_limiter = $_POST[InputLimit];



		#$query="select * from picture where (`종류`='이미지' and (`날자` >= '$_POST[InputStartDay]' and `날자` <='$_POST[InputEndDay]')) limit $_POST[InputLimit]";
		#
		#
		#InputTag가 있을 경우 query.
		if($numbered_person != 0){
			$queryCount= "select count(*) from `picture` inner join `id_with_photo_path` on `id_with_photo_path`.`경로`= `picture`.`경로` where (`종류`='이미지' and `picture`.`날자` >= '$_POST[InputStartDay]' and `날자` <='$_POST[InputEndDay]' and `id_with_photo_path`.`ID` = $numbered_person) limit $file_limiter";

			$query ="select * from `picture` inner join `id_with_photo_path` on `id_with_photo_path`.`경로`= `picture`.`경로` where (`종류`='이미지' and `picture`.`날자` >= '$_POST[InputStartDay]' and `날자` <='$_POST[InputEndDay]' and `id_with_photo_path`.`ID` = $numbered_person) limit $file_limiter";

		}
		

		else {
			$queryCount="select count(*) from picture where (`종류`='이미지' and (`날자` >= '$_POST[InputStartDay]' and `날자` <='$_POST[InputEndDay]'))";

			$query = "select * from picture where (`종류`='이미지' and (`날자` >= '$_POST[InputStartDay]' and `날자` <='$_POST[InputEndDay]')) limit $file_limiter";

		}

		$resultCount=mysqli_query($link,$queryCount) or die("error");

		while($rowCount=mysqli_fetch_array($resultCount)){

			echo "총 갯수는 ".$rowCount[0];
		}


		echo $query;
		$result=mysqli_query($link,$query) or die("error");
		$index=0;
		while($row=mysqli_fetch_array($result)){
			$index=$index+1;


			?>
			<div class="layout">
				<div class="text" align="middle">
				<br>
						<?php
							echo $row['설명']."<br>";
							echo $row['날자']."<br>";
							echo $row['태그']."<br>";
							echo $row['경로']."<br>";
						?>
				</div>
				<div class="polaroid" align="right">
				<img width="100%" alt="" src=<?=$row['경로']?> >
				</div>
			</div>
	<?php
			}
	}
?>

</body>

</html>
	<?php
}
else
{
	echo '로그인하지 않고는 볼수 없습니다.';
}
?>



		</div><!-- #content -->

	</div><!-- #primary -->

	<?php get_sidebar( 'content' ); ?>


</div><!-- #main-content -->

<?php
get_sidebar();
get_footer();

아래 동영상에 나오듯이 조회하는데, 공개 프로그램인지 정확도가 좀 떨어진다. 또한  2018년 이후 찍은 사진을 인식할 수 없다. 해상도를 높여 다시 학습시켜야 할 듯 하다. 이 짓을 완료하기까지 약 일주일정도 걸렸다.

이 글 공유하기:

  • Tweet
발행일 2018-09-27글쓴이 이대원
카테고리 생활코딩 태그 openface, 사진, 얼굴인식, 조회

댓글 남기기응답 취소

이 사이트는 Akismet을 사용하여 스팸을 줄입니다. 댓글 데이터가 어떻게 처리되는지 알아보세요.

글 내비게이션

이전 글

아라비안 나이트

다음 글

자유론

2025 5월
일 월 화 수 목 금 토
 123
45678910
11121314151617
18192021222324
25262728293031
4월    

최신 글

  • common mode, differential mode 2025-05-11
  • signal conditioner, 신호 처리기 2025-05-10
  • strain gage 2025-05-09
  • 칼만 필터 2025-05-01
  • positioner(I/P) 2025-04-26

카테고리

  • 산업계측제어기술사
  • 삶 자국
    • 책과 영화
    • 투자
  • 생활코딩
    • LEGO
    • ROS
    • tensorflow
  • 전기기사
  • 피아노 악보

메타

  • 로그인
  • 엔트리 피드
  • 댓글 피드
  • WordPress.org

페이지

  • 소개
  • 잔여 작업 조회
    • 작업 추가
    • 작업의 사진 조회
    • 작업 수정 페이지
  • 사진
    • GPS 입력된 사진
    • 사진 조회
  • 위치
    • 하기 휴가 방문지
    • 해외 출장

태그

android bash c docker driver FSM gps java kernel LEGO linux mysql network program opcua open62541 plc programmers python raspberry reinforcementLearning ros state space system program tensorflow transfer function 경제 미국 민수 삼국지 세계사 실기 에너지 역사 유전자 일본 임베디드 리눅스 전기기사 조선 중국 채윤 코딩 테스트 통계 한국사 한국어

팔로우하세요

  • Facebook
now0930 일지
WordPress로 제작.