QT 위젯에 이미지를 띄웠는데 정상적으로 나오지 않고 이미지가 반복되거나 왜곡되어 표시되는 경우가 있다

위젯에 이미지를 띄웠는데 왜곡 + 반복 되는 현상이 보인다

 

위젯에 이미지를 띄우려는 경우 QImage 를 생성할텐데, 이 단계에서 이미지의 한 줄당 바이트 수를 지정해주면 깔끔하게 해결된다

 

height, width, channels = img.shape

# 이렇게 작성된 부분을
qimg = QImage(img.data, width, height, QImage.Format_RGB888)

# 이렇게 수정해준다 (4번 째 파라미터가 추가됐다)
qimg = QImage(img.data, width, height, width * channels, QImage.Format_RGB888)

 

 

정상적으로 표시된 이미지

C++ 과 python 두 언어에서 모두 해당되는 해결방법이다

 

참조

https://stackoverflow.com/questions/39057168/qwidget-draws-distorted-angled-qimage

 

QWidget draws distorted angled QImage

I'm working on a homework for my Digital Image Processing class, and I'm using OpenCV with QT Framework. I've created a class ImageDisplay, which is as sub class of the QWidget class. I've using ...

stackoverflow.com

 

블로그 이미지

우송송

,

평소와 같이 USB 웹캠이 아닌, 조명 밝기를 조절하는 컨트롤러를 같이 다루게 될 기회가 생겼다

LED Controller JV502

 

USB 포트에 연결된 상태이므로 장치관리자에 들어가서 Device 이름을 확인해본다

내 경우엔 여기서 Prolific 어쩌구가 JV502 에 해당하는 디바이스 이름이고, 뒤에 붙은 COM5 가 현재 이 장치가 연결된 포트의 번호가 된다 (안보인다면 드라이버 설치 우선 해보자)

 

이 항목들을 우선 파이썬에서 불러와야 한다

방법은 매우 간단하다

 

사용중인 가상환경에서 pyserial 을 우선 설치한다

$ pip install pyserial

 

그리고 다음과 같이 코드를 짜면 끝이다

if __name__ == "__main__":
    import serial.tools.list_ports

    serial_ports = serial.tools.list_ports.comports()
    for ports in serial_ports:
        print(ports)


[OUTPUT]
COM1 - 통신 포트(COM1)
COM5 - Prolific USB-to-Serial Comm Port(COM5)

 

 

이제 원하는 디바이스와 통신하기 위해 우선 연결을 해줘야 한다

우선 코드먼저 보자면 포트이름과 통신속도(baud-rate) 를 넘겨주면 연결이 된다

port_name = "COM5"  # port 이름
baud = 19200  # 디바이스의 통신 속도
ser = serial.Serial(port_name, baud, timeout=0)

여기서 통신속도(baud) 는 장치를 만든 제조사에서 배포한 사양서를 참조하면 확인할 수 있다

 

아래는 내가 사용중인 JV502 디바이스의 사양서 중 일부이다

 

https://www.joy-system.co.kr/product/pdf/JV502_spec.pdf   JV502 컨트롤러의 통신 프로토콜 사양서

 

 

참고로 사양서엔 통신모드가 RS232 로 나와있는데 RS232 는 아래와 같은 포트를 사용하지만 나는 RS232 to USB 를 사용해 usb 포트에 연결해서 쓰는중이다

 

어쨌든 연결까지 됐다면 이제 프로토콜에 따라 통신하면 된다

 

JV502 프로토콜 사양서를 예시로 가져와보면

https://www.joy-system.co.kr/product/pdf/JV502_spec.pdf   JV502 컨트롤러의 통신 프로토콜 사양서

이상한 말이 잔뜩 써져있는데 결국 통신하는데 #A1255& 이런식으로 명령어를 주면 된다는 뜻이다 #A1255& 를 예로들어 설명하자면 

# : 통신시작

'A' : 아스키코드를 사용할 것이란 뜻

'1' : 컨트롤 할 채널 (위 제품의 경우 채널이 2개)

'2, 5, 5' : 위에서 명시한 채널의 전압(밝기) 값을 000 ~ 255  중 최대 밝기로 설정

'&' : 통신종료

 

한번 이해하고나면 매우 쉽다!

 

그럼 이 명령어를 컨트롤러로 보내야 밝기 조절이 가능한데 이것도 매우 간단하다

    data = '#' + 'A' + '1' + '2' + '5' + '5' + '&'  # channel 1 밝기 최대
    ser.write(data.encode())  # 시리얼 통신에 최적화된 바이트 문자열로 통신

이렇게 제품마다 정해진 프로토콜 대로 통신하면 된다

 

아래는 전체코드, 매우매우매우매우매우매우간단하다

    import serial.tools.list_ports

    ser = serial.Serial("COM6", 19200, timeout=0)  # 시리얼 연결
    data = '#' + 'A' + '1' + '2' + '5' + '5' + '&'  # channel 1 밝기 최대
    ser.write(data.encode())  # 명령어 전송
블로그 이미지

우송송

,

파이참을 사용하다 보면 경로에 해당 파일들이 분명히 있는데 파이참에서 빨간 줄이 뜨는 경우가 있다

실행은 문제없이 돌아가지만 Ctrl + 좌클릭을 통해 코드 내부로 들어갈 수 없는 불편함과 무엇보다 눈에 너무 거슬린다

 

 

해결방법은 간단하다

파이참 화면에서 File - settings - Project 에서 Project Structure 탭에 들어간다

 

 

위 화면에서 import 하려는 py 파일들이 있는 폴더를 선택하면 상단의 Sources 와 Excluded 에 불이 들어온다

 

 

 

그 중 Sources 를 눌러 소스폴더로 지정해주면 끝!

 

 

 

 

적용 후 코드로 돌아와보면 빨간줄이 사라져있다

블로그 이미지

우송송

,

최근에 scikit-image  0.20 이 릴리즈되면서 rescale() 을 사용하던 부분에서 multichannel 매개변수가 없다는 에러가 발생했다.

 

바로 앞 0.19 버전 까지만 하더라도 multichannel 옵션이 있었지만 0.20 으로 업데이트되면서 해당 옵션은 deprecate 됐다

0.19 버전의 scikit-image API 설명서

 

 

0.20 버전의 scikit-image API 설명서, multichannel 옵션이 빠져있다

 

 

사용하던 코드에서 multichannel 을 사용중이라면 scikit-image 를 0.19 버전으로 다운그레이드 하거나 해당 라인을 삭제 또는 channel_axis 를 활성화 시키는 방법으로 해결 가능하다.

블로그 이미지

우송송

,

python 에서 OpenCV 를 사용하거나 QT 를 다루다보면 종종 아래와 같은 문제가 발생하기도 한다

QObject::moveToThread: Current thread (0x557f778d2d20) is not the object's thread (0x557f765b2450).
Cannot move to target thread (0x557f778d2d20)

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/ubuntu/anaconda3/envs/torch3.8/lib/python3.8/site-packages/cv2/qt/plugins" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: xcb, eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl.

Aborted (core dumped)

 

사용중인 가상환경에서 opencv-python 을 지우고 openv-python-headless 를 설치하는 방법으로 해결 가능하다

pip uninstall opencv-python
pip install opencv-python-headless

 

 

예전엔 이게 안먹혀서 해결하는데 꽤나 고생했던걸로 기억하는데 이번엔 생각보다 간단하게 해결이 됐다

아래 링크에 다른 해결방법도 있으니 위 방법이 안먹히면 참고

 

참조 : https://github.com/NVlabs/instant-ngp/discussions/300

블로그 이미지

우송송

,

책에서 본적 없지만(아마도..) yolov5 코드를 분석하다 알게된 문법이다

det = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
*poly, conf, cls = det

위 와 같이 det 리스트가 있고 2번 라인처럼 unpack 변수 개수가 다른 코드를 발견했다

 

 

용도는 금방 알 수 있었는데 det 리스트의 맨 뒤 8과 9가 각각 conf 와 cls 에 들어가고 나머지 값들은 list 형태로 poly 변수에 저장된다

print(poly, conf, cls)
>> [0, 1, 2, 3, 4, 5, 6, 7] 8 9

 

보통은 아래처럼 코드를 짰었는데 * 을 사용하는것도 깔끔해보인다

poly = det[:8]
conf = det[8]
cls = det[9]
블로그 이미지

우송송

,

Ubuntu 에서 pip install 을 통해 파이썬 패키지를 설치하는 경우 UnicodeDecodeError 가 발생하는 경우가 종종 있다.

 

 

 

 

내 경우에는 Docker 안에서 우분투를 사용할 때 이런 에러가 나타났는데 Dockerfile 을 빌드할 때 Locale 설정을 해주지 않은 것이 그 이유였다.

 

해결방법은 Dockerfile 의 상단에 아래의 코드를 추가하고 새로 빌드하거나

FROM ubuntu:18.04

#Set the locale
RUN apt-get update
RUN apt-get install locales
ENV LANG ko_KR.UTF-8
ENV LANGUAGE ko_KR.UTF-8
RUN update-locale LANG=ko_KR.UTF-8

 

 

도커를 새로 빌드하긴 싫고 당장의 에러만 해결하고 싶다면 아래의 명령어를 먼저 입력 후 pip install 을 진행해주면 된다

$ export LC_ALL=C.UTF-8

 

블로그 이미지

우송송

,

반복문을 돌리다보면 현재 얼마나 진행되었는지 보고싶을것이다

 

for index in range(1000):
    print(index)

나도 귀찮으니 보통 index 를 출력하는 방법으로 보긴 하지만 로그 창이 더러워지는걸 감수해야 한다

 

 

 

 

이럴 때 코드 몇 줄 추가하면 전체 진행상황을 진행바로 표시해주는 파이썬 패키지가 있다

 

바로 tqdm 이다

 

https://github.com/tqdm/tqdm

 

tqdm/tqdm

A Fast, Extensible Progress Bar for Python and CLI - tqdm/tqdm

github.com

위 사이트에 들어가면 기본적인 tqdm 사용법이 정리되어 있다.

 

for 구문의 범위를 tqdm 으로 묶어주면 자동으로 상태진행바가 표시가 된다

from tqdm import tqdm

for i in tqdm(range(10000000)):
    pass

 

실행결과

현재 진행상황과 경과시간, 남은 시간, 속도를 표시해준다

 

 

 

만약 이미 작성해둔 코드가 복잡해서 중간에 for 문을 끼워놓기 힘든 경우엔 직접 로그를 업데이트 시키는 방법도 있다.

 

from tqdm import tqdm

progress = tqdm(total=10000000)

for i in range(10000000):
    progress.update(1)

 

실행결과

이미 짜여진 코드에 tqdm 을 적용할 때 편한 방법인 듯 하다

 

 

 

 

상태바 앞에 문자나 숫자를 표시하고 싶을 땐 set_description() 또는 set_description_str() 함수를 사용하면 된다

하지만 반복 횟수가 커질수록 반복문이 훨씬 무거워지니 가벼운 반복문에서만 사용하는것을 추천한다

from tqdm import tqdm

progress = tqdm(total=10000000)
for i in range(10000000):
    progress.update(1)
    progress.set_description_str("Progress status : {}".format(i))

 

 

실행결과

위 예시에서 10초 내외로 끝나던 반복문이 20분을 기다리라고 한다

블로그 이미지

우송송

,