
Python, Qt 및 OpenCV로 간단한 WebP 변환 도구를 구축하는 방법
"WebP는 손실 압축과 무손실 압축을 모두 사용하는 이미지 형식으로 애니메이션 및 알파 투명도를 지원합니다. Google에서 개발한 이 파일은 JPEG보다 더 작은 파일을 만들거나 동일한 크기에서 더 높은 품질로 만들도록 설계되었습니다. PNG 및 GIF 이미지 형식"- Wikipedia . 속도는 SEO 최적화의 핵심 요소 중 하나입니다. 개발자는 웹 페이지를 SEO 친화적으로 만들기 위해 WebP를 사용하여 JPEG, PNG 및 GIF를 대체하는 경향이 있습니다. 이 기사에서는 Python, Qt 및 OpenCV를 사용하여 간단한 WebP 변환 도구를 빌드하는 방법을 보여줍니다.
Python 3.x
OpenCV 및 Qt(pyside2 또는 pyside6)
GUI를 디자인하기 위해 열어봅시다

레이블: 로드된 이미지를 표시합니다. 수평 슬라이더: WebP 이미지의 품질을 조정합니다. 푸시 버튼: WebP 변환을 트리거합니다. 목록 위젯: 목록에 이미지 파일을 추가합니다.
UI 디자인이 완료되면
다음 단계는
이제
이미지 파일 또는 폴더를 로드하는 방법에는 두 가지가 있습니다.
버튼을 클릭하여 시스템 파일 대화 상자를 엽니다. 이미지 파일 또는 폴더를 응용 프로그램으로 끌어다 놓습니다.
시스템 파일 대화 상자를 열려면
파일 및 폴더에 대해 끌어서 놓기를 활성화하려면
파일 경로를 얻으면 새 목록 위젯 항목을 만들고 목록 위젯에 추가합니다.
Qt 레이블에 이미지를 표시하려면 Mat를 QImage로 변환해야 합니다.
최신 OpenCV는 WebP를 지원하므로
여러 이미지를 운용할 때의 성능을 고려하여 WebP 변환 코드를 작업자 스레드로 이동합니다. 또한 진행률 표시줄을 표시하면 응용 프로그램의 응답성이 향상됩니다.

https://github.com/yushulx/webp-image-conversion
설치
OpenCV 및 Qt(pyside2 또는 pyside6)
pip install opencv-python pyside2
WebP 변환 도구 개발
1단계: 레이아웃 디자인 및 Python 코드에 UI 로드
GUI를 디자인하기 위해 열어봅시다
Python/Lib/site-packages/PySide2/designer
.
UI 디자인이 완료되면
.ui
에 있는 .py
를 사용하여 pyside2-uic
파일을 Python/Scripts/
파일로 변환합니다.pyside2-uic design.ui -o design.py
다음 단계는
design.py
파일을 로드하고 main.py
파일에 다음 코드를 추가하는 것입니다.import sys
from PySide2.QtGui import QPixmap, QImage, QPainter, QPen, QColor
from PySide2.QtWidgets import QApplication, QMainWindow, QInputDialog
from PySide2.QtCore import QFile, QTimer, QEvent
from PySide2.QtWidgets import *
from design import Ui_MainWindow
import os
import cv2
from PySide2.QtCore import QObject, QThread, Signal
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.setAcceptDrops(True)
def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
이제
main.py
파일을 실행하면 GUI가 표시됩니다.2단계: 위젯을 나열하고 이미지를 표시할 이미지 파일 로드
이미지 파일 또는 폴더를 로드하는 방법에는 두 가지가 있습니다.
시스템 파일 대화 상자를 열려면
QFileDialog
를 사용하여 getOpenFileName
파일을 선택하고 getExistingDirectory
디렉터리를 선택합니다.self.ui.actionOpen_File.triggered.connect(self.openFile)
self.ui.actionOpen_Folder.triggered.connect(self.openFolder)
def openFile(self):
filename = QFileDialog.getOpenFileName(self, 'Open File',
self._path, "Barcode images (*)")
def openFolder(self):
directory = QFileDialog.getExistingDirectory(self, 'Open Folder',
self._path, QFileDialog.ShowDirsOnly)
파일 및 폴더에 대해 끌어서 놓기를 활성화하려면
setAcceptDrops(True)
에 대해 MainWindow
를 설정하고 dragEnterEvent
및 dropEvent
메서드를 재정의해야 합니다.def __init__(self):
# ...
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
event.acceptProposedAction()
def dropEvent(self, event):
urls = event.mimeData().urls()
filename = urls[0].toLocalFile()
if os.path.isdir(filename):
self.appendFolder(filename)
else:
self.appendFile(filename)
event.acceptProposedAction()
파일 경로를 얻으면 새 목록 위젯 항목을 만들고 목록 위젯에 추가합니다.
item = QListWidgetItem()
item.setText(filename)
self.ui.listWidget.addItem(item)
Qt 레이블에 이미지를 표시하려면 Mat를 QImage로 변환해야 합니다.
def showImage(self, filename):
frame = cv2.imread(filename)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image = QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QImage.Format_RGB888)
pixmap = QPixmap.fromImage(image)
self._pixmap = self.resizeImage(pixmap)
self.ui.label.setPixmap(self._pixmap)
return frame
3단계: 슬라이더 값 가져오기 및 이미지를 WebP로 변환
최신 OpenCV는 WebP를 지원하므로
cv2.imwrite()
를 사용하여 이미지를 WebP로 변환하는 것이 편리합니다.quality = int(self.ui.horizontalSlider.value())
frame = cv2.imread(filename)
webp_file = filename.split('.')[0] + '.webp'
cv2.imwrite(webp_file, frame, [cv2.IMWRITE_WEBP_QUALITY, quality])
여러 이미지를 운용할 때의 성능을 고려하여 WebP 변환 코드를 작업자 스레드로 이동합니다. 또한 진행률 표시줄을 표시하면 응용 프로그램의 응답성이 향상됩니다.
class Worker(QObject):
finished = Signal()
progress = Signal(object)
def __init__(self, files, quality):
super(Worker, self).__init__()
self.files = files
self.total = len(files)
self.isRunning = True
self.quality = quality
def run(self):
count = 0
keys = list(self.files.keys())
while self.isRunning and len(self.files) > 0:
filename = keys[count]
count += 1
print(filename)
frame = cv2.imread(filename)
webp_file = filename.split('.')[0] + '.webp'
cv2.imwrite(webp_file, frame, [cv2.IMWRITE_WEBP_QUALITY, self.quality])
self.progress.emit((webp_file, count, self.total))
self.files.pop(filename)
self.finished.emit()
def reportProgress(self, data):
filename, completed, total = data
self.addImage(filename)
if not self.isProcessing:
return
progress = completed
self.progress_dialog.setLabelText(str(completed) +"/"+ str(total))
self.progress_dialog.setValue(progress)
if completed == total:
self.onProgressDialogCanceled()
self.showMessageBox('WebP Conversion', "Done!")
def onProgressDialogCanceled(self):
self.isProcessing = False
self.worker.isRunning = False
self.progress_dialog.cancel()
def runLongTask(self):
if (len(self._all_images) == 0):
return
self.isProcessing = True
self.progress_dialog = QProgressDialog('Progress', 'Cancel', 0, len(self._all_images), self)
self.progress_dialog.setLabelText('Progress')
self.progress_dialog.setCancelButtonText('Cancel')
self.progress_dialog.setRange(0, len(self._all_images))
self.progress_dialog.setValue(0)
self.progress_dialog.setMinimumDuration(0)
self.progress_dialog.show()
self.progress_dialog.canceled.connect(self.onProgressDialogCanceled)
self.thread = QThread()
self.worker = Worker(self._all_images, int(self.ui.label_slider.text()))
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
self.worker.progress.connect(self.reportProgress)
self.thread.start()
4단계: 응용 프로그램을 실행하여 이미지를 WebP로 변환
python main.py

소스 코드
https://github.com/yushulx/webp-image-conversion