2022 캡스톤 디자인 경진대회 (2022년 1학기 1차 예선)
-
wITh you
- 팀장
- 신혜진 (소프트웨어학과 | 3)
- 팀원
- 최은서 (소프트웨어학과 | 3)
- 김지용 (컴퓨터공학과 | 3)
작품영상
-
코딩의 중요성이 커지고 있는 요즘, 전공자들뿐만 아니라 비전공자들도 코딩 교육에 대한 관심과 수요가 많아지고 있습니다. 코로나로 인해 대면 모임이 금지되면서 학교나 동아리 활동을 통해 프로젝트를 수행하는 시간이 적어지고, 혼자 코딩 공부를 하는 시간이 늘어나고 있습니다. 그래서 많은 사람들이 유튜브를 이용해 학습을 수행하고 있는데요, 유튜브는 현재 제일 큰 동영상 플랫폼으로 비용 없이, 여러 질 좋은 강의들을 시청할 수 있다는 장점이 있습니다. 하지만 유튜브는 공부를 위해 만들어진 사이트가 아니기 때문에 여러 불편한 점이 있습니다.
유튜브를 이용해 코딩 공부를 하려면 영상을 재생하고 그 위에 필기를 위한 메모장이나 코드 실습을 위한 ide등 여러 프로그램을 동시에 실행시켜야 합니다. 또, 동영상에서 작성되는 코드는 대부분의 경우 제공되지 않아, 관련 코드를 활용하기 위해서는 영상을 보면서 코드를 타이핑해야 하는데 이런 경우 강의에 온전히 집중하기 어렵습니다. 그리고 코딩 동영상 강의에서는 코드가 한 장면 내에 들어올 만큼 짧지 않기 때문에 대부분 스크롤하며 코드를 작성하는데요, 이때 한 장면씩 일시정지하거나 캡쳐해서 필기하기가 매우 불편합니다.
그렇기 때문에 코드가 나오는 첫 시간과 끝 시간을 지정하면 그 사이에 있는 코드를 모두 추출해서 합쳐주는 기능을 가진 프로그램이 있다면 좋겠다고 생각했습니다. 따라서 유튜브가 제공하는 질 좋은 강의 영상을 학습하는데 더 좋은 환경을 제공하기 위해 강의와 메모, 코드 컴파일은 물론 강의에서 사용되는 코드를 추출하여 제공하는 프로그램을 개발해 이러한 불편함을 해소하고자 하였습니다.
접근성이 높고 검색이 쉬운 유튜브의 장점을 최대한 활용하되, 유튜브를 이용해 코딩 공부를 하면서 느꼈던 단점들을 개선하기 위해 크롬 익스텐션으로 개발하게 되었습니다.
-
기술적 배경
OCR 서버는 Google Tesseract, 이미지 처리는 OpenCV 라이브러리를 사용하였고 Python을 사용하여 전처리 및 후처리를 진행하였습니다. Node.js를 이용해 mp4다운로드, 화면 캡쳐, 한 장면 코드 추출, 여러 장면 코드 추출, mp4삭제 API를 구현하였으며 aws를 사용하여 서버를 구축하였습니다.
클라이언트는 javascript를 이용해 chrome extension으로 개발하여 쉽게 다운받아 사용할 수 있도록 하였고, 컴파일을 위해 jdoodle api, 저장을 위해 firebase를 사용하였습니다.
상세 설계
[프로젝트 아키텍쳐]
저희 프로그램은 크게 크롬 익스텐션 클라이언트와 OCR서버로 이루어져 있습니다. 클라이언트에서는 사용자가 코드 영역, 텍스트 영역을 직접 추가해서 필기할 수 있고, 코드를 추출하고 싶은 화면 영역과 시간대를 지정할 수 있습니다. OCR서버에서는 사용자가 시청하고 있는 Youtube동영상의 URL을 받아 mp4를 다운로드하고 이를 이용해 화면 캡쳐, 한 장면 코드 추출, 여러 장면 코드 추출 기능을 수행합니다.
0. 크롬익스텐션 실행
크롬익스텐션 버튼을 클릭하면 동영상의 유무를 확인해서 동영상이 있는 경우, 크롬익스텐션이 실행되며 UI가 나타납니다.
1. Mp4 중복확인 및 다운로드
사용자가 익스텐션 프로그램을 실행시키면, 이 때 서버에서는 해당 주소의 mp4의 유무를 확인합니다. 다운로드한 동영상의 목록은 mp4 테이블에, 다운로드를 수행중인 동영상은 loading 테이블에 위치합니다. 다운로드 요청이 온 동영상의 URL이 mp4테이블이나 loading 테이블에 있다면 사용자 수를 증가, 다운로드는 수행하지 않습니다. 하지만 동영상이 없다면 loading 테이블에 추가하고 다운로드를 수행합니다. mp4 다운로드가 완료되거나 확인되면 클라이언트에게 해당 video이름을 보내줍니다.
2. 프레임 처리 및 이미지 저장
다운받은 mp4는 cv2라이브러리를 사용해 프레임별로 접근합니다. 사용자가 지정한 시작 시간, 끝 시간을 선택할 경우, 그 사이에 있는 프레임을 추출해 선택한 영역만큼 자르고 이전 프레임과의 차이를 계산해 픽셀 변화가 min보다 크고, max보다 작은 프레임들로 골라 저장합니다. 또한 프레임 간 시간 차이가 적은 프레임이 있다면 하나를 삭제합니다.
화면 캡쳐나 한 장면 추출시에는 해당 시간의 프레임에 접근해 영역만큼 자르고 이를 저장합니다.
3. 이미지 전처리
OCR의 정확도를 높이기 위해 앞에서 저장된 이미지를 큰 사이즈로 resize한뒤, 다음과 같은 전처리 과정을 수행합니다.
1. grayscale을 통해 이미지를 흑백으로 변환합니다. 글자가 검은색, 배경이 흰색일 때 ocr결과의 정확도가 높았기 때문에 thresholding 경계 값을 통해
어두운테마와 밝은 테마를 구분하고, 어두운 테마(검은 배경)일경우 색을 반전시켜 모든 결과에서 글자는 흑, 배경은 백색으로 변경합니다.
2. 실험을 통해 확인한 최적의 방식인 침식연산(erode) 3번 후 팽창연산(dilate)1번 하는 opening을 수행합니다.
3. ocr수행 속도를 높이기 위해 resize를 통해 다시 작은 사이즈로 이미지 크기를 줄입니다.
4. Tesseract OCR (ver. 5.0.0)
OCR을 위해 Google Tesseract라이브러리를 사용하였습니다.
이미지 데이터가 인식한 각 라인을 블록으로 나눠서 ocr을 수행했기 때문에 들여쓰기를 포함해서 결과를 반환할 수 있었습니다. 또한 학습데이터로 eng_best 모델을 이용하였고, 코드에 사용되는 ASCII코드값 33번('!') 부터 126번('~')까지의 문자만 결과로 나오도록 하여 인식률을 높였습니다.
5. 하나의 프레임에 대한 텍스트 후처리 (1차 후처리)
저장한 이미지를 한 프레임씩 OCR해서 그 결과를 다음과 같은 규칙으로 후처리 후, 한 줄씩 배열에 넣습니다.
[규칙1]
● OCR 결과가 3줄 이상일 때 전체에서 예약어(reserved word)가 하나도 없으면 잘못 들어간 프레임으로 판단하고 다음 후처리 단계에서 제외합니다.
● 이전 줄과 시작 공백이 9칸 이상 차이 나면 잘못 들어간 줄로 인식하고 삭제합니다.
● 괄호 안에 있지 않고 세미콜론(';')뒤에 있다면 잘못 인식된 문자로 판단하여 삭제합니다.
● 중간에 공백이 15칸 이상 있으면 코드와 관련이 없는 물체로 판단하고 뒤에 인식된 글자는 삭제합니다.
● 스택을 이용해 괄호개수를 체크 후, 한 줄에 Bitwise OR ('|'),대문자 i ('I'), 소문자 L ('l'), 숫자1 ('1')이 있을 때 빠진 괄호로 바꾸어줍니다.
6. 프레임별 ocr결과 병합 후처리 (2차 후처리)
배열에 들어간 코드 줄간의 유사도를 측정해 기존에 합쳐 놓은 결과에서 알맞은 위치에 코드를 삽입합니다. 다음과 같은 규칙으로 코드 삽입 위치를 알아내었습니다.
[규칙2]
● 시작 공백 개수, 괄호 종류별 개수, 문자(알파벳과 숫자) 종류별 개수, LCS(최장 공통부분 수열)의 길이를 이용해 두 문장간의 유사도를 측정합니다.
● [삽입 유무 판단] 앞선 방식을 바탕으로 유사하지 않음, 조금 유사함, 매우 유사함의 세 단계로 코드 배열의 원소를 분류합니다.
유사하지 않은 문장의 경우 배열에 저장해놓고 유사한 문장이 나왔을 때 그 문장 전에 삽입합니다.
조금 유사하다면 result 배열의 같은줄에 넣고 다음 단계에서 처리합니다. 마지막으로 매우 유사하다면, 삽입하지 않습니다.
● 한 코드 안에는 괄호가 여러개 존재하므로 괄호가 하나만 있는 문장은 위치를 잘못 선정할 수 있기 때문에 유사도를 측정하지 않고 이전에 삽입된 줄
바로 뒤에 삽입합니다.
● 삽입 위치 판단을 위해 저장하려는 코드 배열을 한줄씩 result배열과 비교해, 유사한 원소가 하나만 존재하는 문장을 찾을 때(유사한 원소가 없거나,
여러개라면 다음 줄로 이동)까지 계속 탐색합니다.
● 위의 단계에서 한 문장의 삽입 위치가 정해지면 그 위치로 index를 지정하고 앞서 유사한 원소가 여러개거나 없어서 저장하지 못했던 줄들을 앞에
삽입합니다. 이후의 줄들은 삽입 유무 판단 단계를 수행하여 더이상 추가할 문장이 없을 때까지 반복합니다.
● 끝까지 추가되지 못한 문장은 마지막으로 update된 index뒤에 넣습니다.
7. result 배열 후처리(3차 후처리)
다음과 같은 규칙을 기반으로 비슷한 코드들을 제거하고, 필요없는 줄이나 공백을 제거한 후 애매한 코드들은 주석처리 후 결과로 반환합니다.
[규칙 3]
● 공통된 시작 공백은 제거하고, 시작공백을 제외하고 공백이 2개 이상이면 하나로 변경합니다.
● 글자 수가 네글자 이하인데 +,-,*,/,= 등이 없다면 잘못 인식된 줄로 판단하고 제거합니다.
● 글자 수가 다섯 글자 이상인데 예약어(reserved word)가 하나도 없고 큰따옴표(""), 괄호('()') 내부를 제외하고 단어 6개이상이면 잘못 인식된 줄로
판단하고 제거합니다.
● 이전 줄과 시작 공백을 비교해 9칸이상 차이가 나면 제거합니다.
● 앞선 단계에서 조금 유사함으로 판단된 문장들이 시작 공백 개수를 제외하였을때 매우 유사함으로 바뀌었다면 공백 개수가 중간값인 것을 선택합니다.
● 앞선 단계에서 조금 유사함으로 판단된 후보들 중 예약어(reserved word)의 개수가 가장 많은 문장을 선택합니다.
● 닫는 괄호만 있는 경우, 이전 줄보다 시작 공백이 크면 삭제합니다.
● 마지막 글자가 마침표('.'), 콜론(':') 이면 세미콜론(';')로 변경합니다.
● 중괄호 ('}')의 개수를 확인하여 부족한 수만큼 추가합니다.
● 그 외의 후보들은 주석처리 후 다음줄로 넘겨 반환합니다.
※ 한 장면 추출일 경우 1,3차 후처리만 수행합니다.
8. 결과 반환해서 코드 영역에 보여주기
서버에 요청된 작업(한 장면 or 여러 장면 코드 추출, 화면 캡쳐)이 완료되었다면, 구글 스토리지에 저장된 이미지 URL 또는 완성된 코드 결과를 클라이언트에게 응답합니다.
크롬익스텐션에서 이 결과를 코드 영역에 넣으면 코드 하이라이팅이 되어 에디터에 보이게 됩니다. 이후 원하는 대로 코드를 수정하여 언어를 선택(기본은 C++)하고 실행 버튼을 누르면, 컴파일된 결과 또는 에러 메시지를 받을 수 있습니다.
9. Chrome extension 개발
크롬 익스텐션의 경우 manifest v3를 사용하여 개발하였습니다.
Content-Security-Policy에 의한 DB연동 문제, import/export문제, http://로 시작하는 주소와 통신이 불가능한 점 등 기존 웹사이트 개발과는 다른 점들이 있었습니다. 종료 혹은 URL이 변경시 youtube UI 내부에 삽입된 iframe이 background와 통신하며 작동하는데, CORS policy에 의해 parent에 접근이 불가능한 이슈 등이 있어 이러한 점들을 신경써서 개발하였습니다.
10. 파이어베이스 저장 및 불러오기
텍스트 영역에서 코드 또는 텍스트를 작성하면 실시간으로 파이어베이스에 저장되는데 이때 타입(코드, 텍스트, 이미지), 작성된 내용, 타임스탬프 시간(없다면 NULL)을 배치된 순서대로 저장합니다.
사용자가 다음에 같은 URL을 열었을때 자동으로 내용을 불러와 작성된 노트 위에 이어서 내용을 추가할 수 있습니다.
[역할분담]
김지용 - aws, nodejs를 이용한 ocr서버 구성, 이미지 전처리, Tesseract OCR, 코드 후처리
신혜진 - 프레임 처리, 코드 후처리, 크롬익스텐션 구현, 서버/컴파일 api와 통신, DB 연동
최은서 - 크롬익스텐션 UI 디자인 및 구현, 코드 syntax highlighting 처리
-
우리가 유튜브를 이용해 코딩 공부를 하려면 동영상 창을 열고, 필기할 별도 공간을 마련하고, 코드 실행을 위한 ide 등의 여러 많은 프로그램을 실행시켜야 합니다. 공부할 때 필요한 모든 창을 열었다고 하더라도 여러창을 오가면서 필기도 하랴, 코드도 따라 적으랴, 여간 불편한 것이 아닙니다.
강점 및 차별점
저희 'do IT yourself'는 이러한 불편함을 해소시킬 수 있습니다. 원하는 강의 영상을 찾고 간단히 익스텐션 버튼만 누른다면 그 때부터는 하나의 창 안에서 모든 것을 해결할 수 있습니다. 영상에서 중요한 시간을 타임스탬프를 통해 저장하고, 주요 포인트를 노트를 통해 기록할 수도 있습니다. 또, 드래그 앤 드롭으로 손쉽게 순서를 변경하거나 잘못 추가된 코드, 텍스트 셀을 쉽게 삭제하여 편집해서 나만의 노트를 만들 수 있습니다. 또한, 유튜브의 코딩강의에서 가르쳐주는 코드를 따라 작성하다 보면 어느새 강의에 온전히 집중하지 못하고 코드만 따라 적어내려가기 바쁜 자신을 볼 수 있습니다. 그래서 'do IT yourself'는 영상에서 코드를 추출하는 기능을 제공합니다. 사용자는 단순히 영상에서 코드가 나오는 영역을 지정하고 버튼 하나를 누르면 강의 내의 해당 시간의 코드가 노트에 저장됩니다. 또한 시작시간과 끝 시간을 지정해서 코드 추출버튼을 누른다면 연속된 시간에서 보여지는 코드까지 제공받을 수 있습니다. 이 뿐만 아니라 추출된 코드를 바로 실행해 볼 수 있는 컴파일 기능까지 제공되니 더욱 편리하게 공부할 수 있습니다.
사업 확장성
현재는 유튜브의 강의를 타겟으로 프로젝트를 시작했지만, 더 나아가 백준, 프로그래머스 등의 온라인 알고리즘 문제 사이트의 해설이나 인프런과 같은 코딩강의를 제공하는 업체들과의 제휴를 통해 시너지를 낼 수 있기 때문에 더욱 발전의 여지가 있는 프로젝트라고 생각합니다.
-