휘어지는 LED로 고양이 끈 장난감 만들기

고양이들 레이저 불빛 참 좋아합니다~
아주 환장하지요~
제가 그래서 예전에 선풍기 가지고
레이저 포인트 200% 활용하기
노하우도 공유한 적이 있는데요.

https://blog.naver.com/dolja21/222950006478

그런데 레이저 포인트는
고양이가 직접 움켜쥘 수 있는
물체가 아니기 때문에
허무함을 줄 수 있단 이야기가 있어요.

https://www.salgoonews.com/news/articleView.html?idxno=17690

그리고 무엇보다 밤이 아니면
불빛이 잘 보이지 않아서
냥이가 잘 반응을 하지 않더라구요.

BAEKOKO 배코코 반딧불 낚시대 광섬유 고양이 장난감 고양이용품 반려동물용품, PINK, 1개
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."



그래서 이렇게 반딧불 낚싯대
장난감도 나왔더라구요.
이 아이는 잡을 수 있어서
허무감이 덜할 것 같군요.
근데 불빛이 좀 작단 느낌이 있었어요.
그래서 만들어 봤습니다!
내용은 아래 영상에서 확인할 수 있으세요.


보시고 좋아요 꾹~
구독도 부탁드려요!!!!

재료는 아래 링크로 가시면 구입할 수 있어요.
만 원도 안 되는 가격으로 만들 수 있었습니다~

휘어지는 LED

가온 스위치라인 USB 전원 LED 조명 2m, 웜화이트(옐로우)


"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."



USB 연결형 건전지 소켓
https://www.devicemart.co.kr/goods/view?no=14908041&NaPm=ct%3Dlradjcvj%7Cci%3Dcheckout%7Ctr%3Dppc%7Ctrx%3Dnull%7Chk%3De67ae3608f4328024a878d881f80ab9c4b088abf
Alt text

Alt text

동영상 속의 자막으로부터 SBV 파일 추출하기

  • 저는 블로그 뿐만 아니라 유튜브 채널도 운영하고 있는데요.
  • 비록 미미한 구독자수와 형편없는 조회수를 자랑하지만, 그래도 1년 넘게 꾸준히 영상을 업로드하고 있습니다.
  • 제가 만드는 컨텐츠들은 주로 영상속에 포함되어 렌더링되는 자막에 크게 의존하고 있는데요. 내용을 이해하는데 이 자막들이 상당히 중요합니다.
  • 그런데 구독자들 중에 외국인들이 생기면서 몇 가지 고민거리가 생겼어요. 그 고민거리는 아래와 같습니다.
    • 적어도 영어 자막은 제공하고 싶다.
    • 사용하는 영상제작 프로그램에서 sbv와 같은 시퀀싱 자막 파일을 추출할 수 없다.
    • 매번 유튜브 자막제작툴을 이용하고 있는데, 타임 레인지 맞추는게 너무 불편하다.

자막편집의고통

  • 이런 고민을 해결해보려고 여러가지 프로그램을 찾아봤지만, 뾰족한 대안을 찾기어려웠어요.
  • 그래서! 직접 만들어 봤습니다. 전체코드는 아래 링크로 공유할게요.
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
위 광고를 클릭해주시면 코드가 나타납니다.
import easyocr
from difflib import SequenceMatcher
import cv2
import os
import numpy
import scipy.cluster.hierarchy as hcluster
import matplotlib.pyplot as plt
from datetime import timedelta

def get_text_from_frame(img_file):
    reader = easyocr.Reader(['ko','en']) # this needs to run only once to load the model into memory
    result = reader.readtext(img_file)
    if len(result) > 0:
        text = ''
        for item in result:
            if len(item) > 1:
                text = "%s %s" % (text, item[1])
        return text
    return ''

def text_diff(t1, t2):
    return SequenceMatcher(None, t1, t2).ratio()

def frame_to_time(fps, frame):
    as_msecond = (frame / fps) * 1000
    td = timedelta(milliseconds=as_msecond)
    if str(td).find('.') == -1:
        return "%s.000" % str(td)
    return str(td)[:-3]

filepath = '[추출할동영상].mp4'
video = cv2.VideoCapture(filepath)
if not video.isOpened():
    print("Could not Open :", filepath)
    exit(0)
length = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = video.get(cv2.CAP_PROP_FPS)
fps2 = int(fps/2)
before_text = ''
count = 0
before_diff = 0
start_frame = 0
end_frame = 0
data = []
text_count = {}
while(video.isOpened() and count < length):
    ret, image = video.read()
    if(int(video.get(1)) % fps2 == 0): #앞서 불러온 fps 값을 사용하여 0.5초마다 추출
        cv2.imwrite('frame.png', image)
        text = get_text_from_frame('frame.png')
        diff = text_diff(text, before_text)
        if diff < 0.75:
            diff = 0.0
        else:
            diff = 1.0
        if text == '':
            diff = 0.0
        else:
            if text in text_count:
                text_count[text] = text_count[text] + 1
            else:
                text_count[text] = 1
        print("%s, %s" % (diff, text))
        if before_diff == 0.0 and diff == 1.0:
            start_frame = count
        elif before_diff == 1.0 and diff == 0.0:
            end_frame = count
            sorted_text_count = sorted(text_count.items(), key = lambda item: item[1], reverse = True)
            print(sorted_text_count)
            if sorted_text_count[0][0] != '':
                data.append([start_frame, end_frame, sorted_text_count[0][0]])
            text_count = {}
        before_diff = diff
        before_text = text

    print("%d / %d" % (count, length))
    if count < length:
        count = count + 1

if start_frame > end_frame:
    end_frame = count
    sorted_text_count = sorted(text_count.items(), key = lambda item: item[1], reverse = True)
    print(sorted_text_count)
    if sorted_text_count[0][0] != '':
        data.append([start_frame, end_frame, sorted_text_count[0][0]])

video.release()

f = open('[자막파일명].sbv', 'w')
for cap in data:
    start_time = frame_to_time(fps, cap[0])
    end_time = frame_to_time(fps, cap[1])
    f.write("%s,%s\n" % (start_time, end_time))
    f.write("%s\n\n" % cap[2])
f.close()

전체코드 다운로드

  • 주의사항
    • CUDA를 지원하는 GPU가 없을 경우 CPU만 이용해서 OCR을 수행하기 때문에 매우 느립니다.
    • GPU가 없다면 구글 코랩에서 하드웨어 가속기를 이용해보세요.
  • 원래는 번역까지 자동으로 되게하는 코드를 작성하려고 했었습니다만…
  • OCR의 품질이 번역 가능할 수 있는 정도까지 결과를 만들어내지는 못합니다.
  • 일단 타임레인지를 잡아내는 정도에서 만족해 보려고 하구요.
  • 아래 영상은 자동으로 추출한 타임레인지의 SBV 파일에서 영어 번역만 수행해서 올린 것 입니다.

IntelliJ Idea Remote Development 사용시 멀티 프로젝트를 위한 모듈 설정

예전에 인텔리제이 원격개발 환경에서 프로젝트에 모듈을 지정하는 방법에 대해서 소개한 바가 있습니다.

이때는 1개의 모듈을 사용하는 경우를 소개한 것 인데요. 필요에 따라서는 하나의 프로젝트 환경에 여러개의 모듈을 사용하는 경우가 있을 수 있죠? 아래 그림처럼 말이에요~ Alt text

방법은 간단합니다. 먼저 1개의 모듈일 때 처럼, 추가하려는 모듈의 폴더에 들어가서 아래 작업을 수행해 주세요.

먼저 .idea 폴더 내에 [프로젝트명].iml 파일을 만들고 아래와 같이 기입합니다. 파이썬 프로젝트 일 때의 예제에요.

<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$" />
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
  </component>
</module>

그런다음 최초에 지정되어 있던 모듈의 폴더에서 아래처럼 내용을 수정합니다.

최초에 지정된 모듈의 .idea 폴더의 modules.xml을 수정합니다.

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
위 광고를 클릭해주시면 코드가 나타납니다.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
    <component name="ProjectModuleManager">
        <modules>
            <module fileurl="file://$PROJECT_DIR$/.idea/[프로젝트1명].iml" filepath="$PROJECT_DIR$/.idea/[프로젝트1명].iml" />
            <module fileurl="file://[프로젝트2경로]/.idea/[프로젝트2명].iml" filepath="[프로젝트2경로]/.idea/[프로젝트2명].iml" />
        </modules>
    </component>
</project>

프로젝트2경로는 절대경로로 해도되고, 프로젝트1의 경로에 맞춰서 상대경로로 해도됩니다.