Qt Python으로 문서 스캔 및 바코드 인식 애플리케이션 구축

몇 달 전에 저는 Qt Python과 Dynamsoft Barcode Reader로 구축된 교차 플랫폼desktop barcode reading application을 게시했습니다. 지원되는 입력 소스에는 실시간 카메라 스트림, 이미지 파일 및 스크린샷이 포함됩니다. 이 글에서는 문서 스캐너를 입력 소스로 설정하겠습니다. 문서 스캐닝에 사용되는 SDK는 크로스 플랫폼 JavaScript 라이브러리이며 Windows, macOS 및 Linux를 지원하는 Dynamic Web TWAIN 입니다.

전제 조건



  • SDK
  • Dynamic Web TWAIN

  • Dynamsoft 바코드 리더

    pip install dbr
    


  • Qt

    pip install PyQt5
    




  • 특허


  • 크로스 플랫폼 문서 스캐닝 및 바코드 인식 애플리케이션 구축 단계



    HTML5와 Python 코드를 결합한 하이브리드 애플리케이션을 만들 것입니다.

    1. Qt 위젯으로 Qt 애플리케이션 만들기



    필요한 Qt 위젯은 다음과 같습니다.
  • QWebEngineView : HTML 및 JavaScript 코드를 로드하는 데 사용됩니다. Dynamic Web TWAIN API로 스캔한 문서 이미지를 보여줍니다.
  • QPushButton : 하나는 이미지 획득용이고 다른 하나는 바코드 디코딩용입니다.
  • QTextEdit : 바코드 결과를 표시합니다.

  • 먼저 빈 Qt 창을 만듭니다.

    from PyQt5.QtWidgets import *
    from PyQt5.QtCore import *
    from PyQt5.QtGui import *
    from PyQt5.QtWebEngineWidgets import QWebEngineView
    from PyQt5.QtWebChannel import QWebChannel
    
    app = QApplication([])
    win = QWidget()
    win.setWindowTitle('Dynamic Web TWAIN and Dynamsoft Barcode Reader')
    win.show()
    app.exec_()
    


    그런 다음 레이아웃을 만들고 여기에 위젯을 추가합니다.

    class WebView(QWebEngineView):
        def __init__(self):
            QWebEngineView.__init__(self)
    
    layout = QVBoxLayout()
    win.setLayout(layout)
    
    view = WebView()
    bt_scan = QPushButton('Scan Barcode Documents')
    bt_read = QPushButton('Read Barcode')
    text_area = QTextEdit()
    
    layout.addWidget(view)
    layout.addWidget(bt_scan)
    layout.addWidget(bt_read)
    layout.addWidget(text_area)
    


    바로 가기 키는 데스크톱 응용 프로그램에 편리합니다. R를 사용하여 웹 보기를 다시 로드하고 Q를 사용하여 애플리케이션을 종료합니다.

    def keyPressEvent(event):
        if event.key() == Qt.Key.Key_Q:
            win.close()
        elif event.key() == Qt.Key.Key_R:
            refresh_page()
    
    win.keyPressEvent = keyPressEvent
    


    지금까지 기본 UI가 완료되었습니다. 애플리케이션을 실행할 수 있습니다.

    python app.py
    


    2. Qt 애플리케이션에서 HTML 및 JavaScript 코드 로드



    Dynamic Web TWAIN SDK는 Dynamic Web TWAIN SDK <version>\Samples\ 폴더에 다양한 샘플 코드를 제공합니다. Samples\Scan\SourceList.htmlSamples\Scan\Resources를 Python 프로젝트의 루트에 복사합니다.
    SourceList.htmlindex.html로 이름을 바꾼 다음 다음 Python 코드를 추가하여 index.html 및 모든 관련 리소스 파일을 로드합니다.

    import os
    
    class WebView(QWebEngineView):
        def __init__(self):
            QWebEngineView.__init__(self)
    
            # Load web page and resource files to QWebEngineView
            file_path = os.path.abspath(os.path.join(
                os.path.dirname(__file__), "index.html"))
            local_url = QUrl.fromLocalFile(file_path)
            self.load(local_url)
    


    Python 애플리케이션을 다시 실행하면 웹 페이지가 표시됩니다.

    3. Python과 JavaScript 간의 통신 설정



    Python과 JavaScript 간의 통신은 애플리케이션의 핵심 부분입니다.
    index.html에는 문서 스캔을 위한 AcquireImage() 기능이 포함되어 있습니다.

    function AcquireImage() {
        if (DWObject) {
            var OnAcquireImageSuccess, OnAcquireImageFailure;
            OnAcquireImageSuccess = OnAcquireImageFailure = function () {
                DWObject.CloseSource();
            };
    
            DWObject.SelectSourceByIndex(document.getElementById("source").selectedIndex); //Use method SelectSourceByIndex to avoid the 'Select Source' dialog
            DWObject.OpenSource();
            DWObject.IfDisableSourceAfterAcquire = true;    // Scanner source will be disabled/closed automatically after the scan.
            DWObject.AcquireImage(OnAcquireImageSuccess, OnAcquireImageFailure);
        }
    }
    


    Python 측에서 runJavaScript를 호출하여 JavaScript 함수를 실행할 수 있습니다.

    def read_barcode():
        frame = view.page()
        frame.runJavaScript('AcquireImage();')
    
    bt_scan.clicked.connect(acquire_image)
    


    스캔 프로세스가 완료되면 현재 이미지가 메모리에 보관됩니다. base64 문자열로 변환할 수 있습니다.

    function getCurrentImage() {
        if (DWObject) {
            DWObject.ConvertToBase64(
                [DWObject.CurrentImageIndexInBuffer],
                Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG,
                function (result, indices, type) {
                    // TODO:
                },
                function (errorCode, errorString) {
                    console.log(errorString);
                }
            );
        }
    }
    


    JavaScript에서 Python으로 base64 문자열을 어떻게 전달할 수 있습니까? 정답은 QWebChannel 입니다. index.html에는 QtCreator가 설치되어 있는 경우 qwebchannel.js 폴더에서 찾을 수 있는 Qt\Examples\Qt-5.12.11\webchannel\shared가 포함되어 있습니다. 그런 다음 다음 코드를 추가하여 base64 문자열을 보냅니다.

    var backend;
    new QWebChannel(qt.webChannelTransport, function (channel) {
        backend = channel.objects.backend;
    });
    
    function getCurrentImage() {
        if (DWObject) {
            DWObject.ConvertToBase64(
                [DWObject.CurrentImageIndexInBuffer],
                Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG,
                function (result, indices, type) {
                    backend.onDataReady(result.getData(0, result.getLength()))
                },
                function (errorCode, errorString) {
                    console.log(errorString);
                }
            );
        }
    }
    

    onDataReady 함수는 Python 측에서 구현해야 합니다.

    class Backend(QObject):
        @pyqtSlot(str)
        def onDataReady(self, base64img):
    
    class WebView(QWebEngineView):
        def __init__(self):
            QWebEngineView.__init__(self)
    
            # Load web page and resource files to QWebEngineView
            file_path = os.path.abspath(os.path.join(
                os.path.dirname(__file__), "index.html"))
            local_url = QUrl.fromLocalFile(file_path)
            self.load(local_url)
            self.backend = Backend(self)
            self.channel = QWebChannel(self.page())
            self.channel.registerObject('backend', self.backend)
            self.page().setWebChannel(self.channel)
    
    def read_barcode():
        frame = view.page()
        frame.runJavaScript('getCurrentImage();')
    
    bt_read.clicked.connect(read_barcode)
    


    4. 스캔한 문서에서 바코드 디코딩



    마지막으로 Dynamsoft Barcode Reader를 사용하여 base64 문자열에서 바코드를 디코딩하고 텍스트 영역에 결과를 표시할 수 있습니다.

    from dbr import *
    import base64
    
    # Initialize Dynamsoft Barcode Reader
    reader = BarcodeReader()
    # Apply for a trial license https://www.dynamsoft.com/customer/license/trialLicense?product=dbr
    reader.init_license('LICENSE-KEY')
    
    class Backend(QObject):
        @pyqtSlot(str)
        def onDataReady(self, base64img):
            imgdata = base64.b64decode(base64img)
    
            try:
                text_results = reader.decode_file_stream(bytearray(imgdata), '')
                if text_results != None:
                    out = ''
                    for text_result in text_results:
                        out += "Barcode Format : "
                        out += text_result.barcode_format_string + '\n'
                        out += "Barcode Text : "
                        out += text_result.barcode_text + '\n'
                        out += "-------------------------------------------------" + '\n'
    
                    text_area.setText(out)
            except BarcodeReaderError as bre:
                print(bre)
    




    소스 코드



    https://github.com/yushulx/Qt-scan-document-read-barcode

    좋은 웹페이지 즐겨찾기