The Automation of Collecting Data for Construction Information Technology Research

3 분 소요

The Automation of Collecting Data for Construction Information Technology Research

개발 이유

교수님께서 기존에 수집한 Training Sets이 부족한 문제로 인해 Training Performance가 좋지 못하여 저희에게 Datasets을 수집하는 과제를 제시해주셨습니다.

이에 저는 기존에 Crawling 경험이 있기 때문에 이를 이용하면 일일히 Datasets들을 마련하지 않아도 될 것 같다는 판단하에 본 Automation을 기획 및 개발을 시작하게 되었습니다.

그러나 다음과 같이 찾고자 하는 Datasets 외에도 다른 목적에 부합하지 않는 Data들이 섞여있어 이를 해결할 방안을 고민하던 중, 비록 아직 Datasets들이 부족하여 Performance가 좋지는 못하지만, 기존 모델을 이용하여 Classification을 진행한다면 일일히 이를 하는 것보다 훨씬 효율적으로 작업 및 이로 인해 시간 단축을 할 수 있을 것이라는 생각을 하게 되었습니다.

Figure

개발 환경

개발 도구

  • Visual Studio
  • Visual Studio Code

개발 언어

  • C++
  • Python

라이브러리

  • BeautifulSoup
  • Win32 API

원리

먼저 찾고자 하는 Datasets들에 대한 기존 학습 가중치를 준비한 다음, Crawler를 이용하여 해당 Datasets들을 수집합니다.

그 다음, Darknet의 인자로 Weights에 대한 경로를 전달하여 Darknet에 이를 Load하고, Predict(Classification)를 진행합니다.

분류의 결과로부터 Rule-based로 일정 Score 이상/이하인 경우에 사전에 지정한 Directory로 결과 Image들이 이동하게끔 했습니다.

종합하면, 이러한 순서를 차례대로 진행하는 Windows 기반 Host와 이미지 Datasets들을 수집하는 Crawler, Datasets들의 분류를 진행하는 Darknet, 마지막으로 분류 Performance를 측정하는 Analyzer가 있습니다.

코드

Host

#include <boost/format.hpp>
#include <string>
#include <cstdio>
#include <tchar.h>
#include <Windows.h>

using namespace std;
using boost::format;
using boost::io::group;

TCHAR* StringToTChar(string& s) {
	size_t ori_s = 0, conv_s = 0;
	wchar_t* t = NULL;

	ori_s = strlen(s.c_str()) + 1;
	t = new wchar_t[ori_s];
	mbstowcs_s(&conv_s, t, ori_s, s.c_str(), _TRUNCATE);
	
	return (TCHAR*)t;
}

int _tmain(int argc, TCHAR* argv[]) {
	string key_s = "cell fender";
	string thres = "0.80";
	string class_id = "1";

	string wc_p = "C:/darknet_c";
	string dn_p = "C:/darknet";
	string pc_p = "C:/darknet_p";

	string wc_cb = str(format("%1%/test.exe %2%") % wc_p % key_s);
	string dn_cb = str(format("cmd.exe /c cd %1% && darknet.exe detector test data/obj.data cfg/yolo-obj.cfg backup/yolo-obj_4000.weights -ext_output -dont_show -out result.json < data/img.txt") % dn_p);
	string pc_cb = str(format("%1%/judge.exe %2% %3%") % pc_p % thres % class_id);

	STARTUPINFO wc = { 0, };
	STARTUPINFO dn = { 0, };
	STARTUPINFO pc = { 0, };

	PROCESS_INFORMATION wc_pr;
	PROCESS_INFORMATION dn_pr;
	PROCESS_INFORMATION pc_pr;

	DWORD wc_r = NULL;
	DWORD dn_r = NULL;
	DWORD pc_r = NULL;

	TCHAR* wc_c = StringToTChar(wc_cb);
	TCHAR* dn_c = StringToTChar(dn_cb);
	TCHAR* pc_c = StringToTChar(pc_cb);

	wc.cb = sizeof(wc);
	dn.cb = sizeof(dn);
	pc.cb = sizeof(pc);

	CreateProcess(NULL, wc_c, NULL, NULL, TRUE, 0, NULL, NULL, &wc, &wc_pr);
	WaitForSingleObject(wc_pr.hProcess, INFINITE);
	CloseHandle(wc_pr.hThread);
	
	CreateProcess(L"c:/windows/system32/cmd.exe", dn_c, NULL, NULL, TRUE, 0, NULL, NULL, &dn, &dn_pr);
	WaitForSingleObject(dn_pr.hProcess, INFINITE);
	CloseHandle(dn_pr.hThread);

	CreateProcess(NULL, pc_c, NULL, NULL, TRUE, 0, NULL, NULL, &pc, &pc_pr);
	WaitForSingleObject(pc_pr.hProcess, INFINITE);
	CloseHandle(pc_pr.hThread);


	GetExitCodeProcess(wc_pr.hProcess, &wc_r);
	GetExitCodeProcess(dn_pr.hProcess, &dn_r);
	GetExitCodeProcess(pc_pr.hProcess, &pc_r);

	if (wc_r == -1 || dn_r == -1 || pc_r == -1)
		return -1;

	CloseHandle(wc_pr.hProcess);
	CloseHandle(dn_pr.hProcess);
	CloseHandle(pc_pr.hProcess);

	return 0;
}

Crawler

import urllib.request
from urllib.parse import quote_plus
from bs4 import BeautifulSoup
from selenium import webdriver
import time
import sys
import os
import shutil

def remove_folder(path):
    # check if folder exists
    if os.path.exists(path):
         # remove if exists
         shutil.rmtree(path) 

keyword = ""

img_path = "C:/darknet/data/import"
img_data_path = "C:/darknet/data"

SCROLL_PAUSE_SEC = 1

if os.path.isdir(img_path):
    remove_folder(img_path)

if not os.path.isdir(img_path):
    os.makedirs(img_path)

def scroll_down():
    global driver
    last_height = driver.execute_script("return document.body.scrollHeight")

    while True:
        driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
        time.sleep(SCROLL_PAUSE_SEC)
        new_height = driver.execute_script("return document.body.scrollHeight")

        if new_height == last_height:
            time.sleep(SCROLL_PAUSE_SEC)
            new_height = driver.execute_script("return document.body.scrollHeight")

            try:
                driver.find_element_by_class_name("mye4qd").click()
            except:

               if new_height == last_height:
                   break


        last_height = new_height

try:
    keyword += sys.argv[1]

except:
    print("Insufficient arguments")
    sys.exit()

try:
    sys.argv[2]

    keyword += (" " + sys.argv[2])

except:
    pass

url = 'https://www.google.com/search?q={}&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjgwPKzqtXuAhWW62EKHRjtBvcQ_AUoAXoECBEQAw&biw=768&bih=712'.format(keyword)

driver = webdriver.Chrome()
driver.get(url)

time.sleep(1)

scroll_down()

html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')
images = soup.find_all('img', attrs={'class':'rg_i Q4LuWd'})

print('number of img tags: ', len(images))

n = 1
for i in images:

    try:
        imgUrl = i["src"]
    except:
        imgUrl = i["data-src"]
        
    with urllib.request.urlopen(imgUrl) as f:
        with open(img_path + '/' + keyword + str(n) + '.jpg', 'wb') as h:
            img = f.read()
            h.write(img)

    n += 1

file_list = os.listdir(img_path + '/')
file_list_jpg = [file for file in file_list if file.endswith(".jpg")]

try:
    os.remove(img_data_path + '/' + 'img.txt')
except:
    pass

with open(img_data_path + '/' + "img.txt", "w") as f:
    for file in file_list_jpg:
        file = file.strip()
        f.write(img_path + '/' + file + '\n')

Analyzer

import os
import sys
import json
import shutil

try:
    thres = float(sys.argv[1])
    class_menu = int(sys.argv[2])
except:
    print("Not Float Arguments")
    sys.exit()

if len(sys.argv) != 3:
    print("Insufficient arguments")
    sys.exit()

ori = 'C:/darknet/data/import'

with open("C:/darknet/result.json", "r") as f:
    j_data = json.load(f)

    for i, j in enumerate(j_data):
        inner_objects = j_data[i]["objects"]
        file_path = j_data[i]["filename"].split('/')

        if not os.path.isdir(ori + '/' + 'want'):
            os.makedirs(ori + '/' + 'want')
        
        if not os.path.isdir(ori + '/' + 'need_check'):
            os.makedirs(ori + '/' + 'need_check')

        try:
            inner_objects[0]["class_id"]

            for k, m in enumerate(inner_objects):
                if inner_objects[k]["confidence"] >= thres and inner_objects[k]["class_id"] == class_menu:
                    file_path.insert(-1, 'want')
                    edit_file_path = '/'.join(file_path)
                    
                    try:
                        shutil.move(j_data[i]["filename"], edit_file_path)
                    except:
                        pass
                else:
                    file_path.insert(-1, 'need_check')
                    edit_file_path = '/'.join(file_path)

                    try:
                        shutil.move(j_data[i]["filename"], edit_file_path)
                    except:
                        pass

        except:
            file_path.insert(-1, 'need_check')
            edit_file_path = '/'.join(file_path)

            try:
                shutil.move(j_data[i]["filename"], edit_file_path)
            except:
                pass

댓글남기기