본문 바로가기
파이썬 프로그래밍/PyQt5 공부하기

5. PyQt5와 opencv 연동하기 : 이미지 불러오기

by Majestyblue 2024. 11. 21.

참고(이분 책 보고 opencv 공부 많이 했다 ㅎㅎ)

OpenCV(Python) + PyQt

 

OpenCV(Python) + PyQt

OpenCV로 영상처리나 컴퓨터 비전을 처리하고 나서 결과를 화면에 표시하려면 결국 창을 띄워야 하는데, OpenCV의 imshow() 함수 만으로는 역부족인 경우가 많습니다. 파이썬 언어에서 인기 있는 멀티

blog.xcoda.net

 

결론을 이야기하자면 opencv로 작업하려면 numpy로 배열을 받고 QImage → QPixmap으로 변환해야 한다.

 

import sys, cv2
from PyQt5.QtWidgets import *
from PyQt5.QtGui import * 

def open_movie():
    print("동영상 불러오기를 성공하였습니다.")

class MyWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        
        self.setWindowTitle("physics Lab")
        self.setGeometry(300, 300, 400, 400) 
        self.setWindowIcon(QIcon("physics.png"))
        
        # 상태바 생성
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        
        self.img_label = QLabel(parent=self)
        self.img_label.move(10, 10)
        
        self.btn = QPushButton(text = "이미지 열기", parent = self)
        self.btn.move(250, 10)
        self.btn.clicked.connect(self.btn_clicked)
        
        self.btn2 = QPushButton(text = "이미지 삭제", parent = self)
        self.btn2.move(250, 50)
        self.btn2.clicked.connect(self.btn2_clicked)
        
    def btn_clicked(self):
        fname, _ = QFileDialog.getOpenFileName(self, "Choose File", "", "All files(*)")
        # 사용자가 파일 선택을 취소한 경우
        if not fname:  # fname이 빈 문자열일 경우
            self.status_bar.showMessage("파일 선택이 취소되었습니다.")
            return  # 아무 작업도 하지 않고 함수 종료

        img = cv2.imread(fname)

        if img is None:  # 이미지가 제대로 읽히지 않은 경우
            self.status_bar.showMessage("이미지를 불러오는 데 실패하였습니다.")
            return  # 에러 처리 후 함수 종료

        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        h, w, c = img.shape
        qImg = QImage(img.data, w, h, w*c, QImage.Format_RGB888)
        self.pixmap = QPixmap.fromImage(qImg)
        self.img_label.resize(200, 200)
        self.pixmap = self.pixmap.scaled(200, 200)
        self.img_label.setPixmap(self.pixmap)
        
        self.status_bar.showMessage("이미지를 불러오는 데 성공하였습니다.")
        
    def btn2_clicked(self):
        self.img_label.clear()
        self.status_bar.clearMessage()


app = QApplication(sys.argv)

win = MyWindow()

win.show()
app.exec_()

 

여기서 주목해야 할 것은 btn_clicked 함수이다.

 

 

fname, _ = QFileDialog.getOpenFileName(self, "Choose File", "", "All files(*)")
  • QFileDialog.getOpenFileName 함수를 호출하여 파일 선택 창을 엽니다. 사용자가 선택한 파일의 경로는 fname에 저장됩니다.
  • "Choose File"은 다이얼로그의 제목이며, ""는 기본 경로, "All files(*)"는 선택 가능한 파일 형식을 의미합니다.

 

if not fname:
    self.status_bar.showMessage("파일 선택이 취소되었습니다.")
    return
  • fname이 빈 문자열인지 확인합니다. 빈 문자열인 경우 사용자가 파일 선택을 취소한 것이므로, 사용자에게 메시지를 출력하고 함수를 종료합니다.

 

img = cv2.imread(fname)
  • cv2.imread 함수를 사용하여 선택한 파일 경로 fname에서 이미지를 읽어옵니다. 이때 img 변수는 이미지 데이터를 포함하는 NumPy 배열입니다.

 

if img is None:
    self.status_bar.showMessage("이미지를 불러오는 데 실패하였습니다.")
    return
  • cv2.imread가 실패했을 경우(img가 None인 경우)에도 적절한 에러 메시지를 출력하고 함수를 종료합니다.

 

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  • OpenCV는 기본적으로 이미지를 BGR 형식으로 읽어옵니다. 따라서, 이를 RGB 형식으로 변환하기 위해 cv2.cvtColor 함수를 사용합니다.
  • cv2.COLOR_BGR2RGB는 BGR 색상 공간에서 RGB 색상 공간으로의 변환을 나타냅니다.

 

h, w, c = img.shape
  • img.shape를 통해 이미지의 높이(h), 너비(w), 채널 수(c)를 가져옵니다. 이 정보는 QImage 객체를 생성할 때 필요합니다.

 

qImg = QImage(img.data, w, h, w*c, QImage.Format_RGB888)
  • QImage는 PyQt에서 이미지를 다루기 위한 객체입니다. 이 객체는 OpenCV의 NumPy 배열을 사용하여 생성됩니다.
  • img.data는 이미지의 픽셀 데이터에 대한 포인터입니다.
  • w, h는 이미지의 너비와 높이입니다.
  • w*c는 각 행의 바이트 수 (너비 * 채널 수)입니다.
  • QImage.Format_RGB888는 RGB 형식을 지정합니다.

 

self.pixmap = QPixmap.fromImage(qImg)
  • QPixmap.fromImage 메서드를 사용하여 QImage를 QPixmap으로 변환합니다. QPixmap은 화면에 이미지를 표시하는 데 최적화된 객체입니다.

 

self.img_label.resize(200, 200)
self.pixmap = self.pixmap.scaled(200, 200)
self.img_label.setPixmap(self.pixmap)
  • self.img_label.resize(200, 200)는 이미지 라벨의 크기를 200x200 픽셀로 설정합니다.
  • self.pixmap.scaled(200, 200)는 QPixmap을 200x200 픽셀로 조정합니다.
  • self.img_label.setPixmap(self.pixmap)는 조정된 QPixmap을 라벨에 설정하여 이미지를 화면에 표시합니다.

 

실행결과

이미지 열기를 클릭하면...

 

 

파일 열기창이 뜬다.

 

 

불러오기 성공! (Status bar 상태 바에도 뜬다)

 

 

이미지 삭제를 누르면 사라진다.