Qt QCamera를 사용하여 웹캠으로 바코드 스캐너를 구현하는 방법
Windows에서 QCamera용 CMake 구성
Qt 응용 프로그램에서 웹캠 지원을 추가하려면
QCamera
라이브러리에서 QtMultimedia
클래스를 가져와야 합니다. 내 Windows Qt 환경에서는 QtMultimedia
라이브러리를 포함하지 않는 Qt 6.1.2만 설치했습니다. Qt documentation에 따르면 Qt 5에서 QCamera
클래스를 찾을 수 있습니다.따라서 Qt 5.12.11을 설치하려면 Qt 유지 관리 도구를 실행해야 합니다.
그런 다음 PATH 환경 변수를 업데이트하여 빌드 도구를 다운그레이드합니다.
QCamera 헤더 파일은
Qt/5.12.11/mingw73_64/include/QtMultimedia/qcamera.h
에 있습니다.CMakeLists.txt
파일에서 Qt 버전을 5로 변경하고 QtMultimedia
라이브러리를 연결합니다.cmake_minimum_required(VERSION 3.5)
project(BarcodeReader VERSION 0.1 LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (CMAKE_HOST_WIN32)
link_directories("${PROJECT_SOURCE_DIR}/platform/windows/lib/")
elseif(CMAKE_HOST_UNIX)
link_directories("${PROJECT_SOURCE_DIR}/platform/linux/")
endif()
include_directories("${PROJECT_SOURCE_DIR}/include/")
find_package(Qt5 COMPONENTS Widgets REQUIRED)
find_package(Qt5MultimediaWidgets REQUIRED)
set(PROJECT_SOURCES
main.cpp
mainwindow.cpp
mainwindow.h
mainwindow.ui
myvideosurface.h
myvideosurface.cpp
)
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
if (CMAKE_HOST_WIN32)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets Qt5::MultimediaWidgets "DBRx64")
elseif(CMAKE_HOST_UNIX)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets Qt5::MultimediaWidgets "DynamsoftBarcodeReader")
endif()
if(CMAKE_HOST_WIN32)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${PROJECT_SOURCE_DIR}/platform/windows/bin/"
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
endif()
myvideosurface.h
파일과 myvideosurface.cpp
파일은 웹캠 미리보기를 표시하고 실시간으로 바코드를 인식하는 데 사용됩니다. 구현에 대해서는 다음 섹션에서 설명하겠습니다.실시간 바코드 스캐닝
QCamera에는 웹캠 미리보기를 표시하는 데 사용할 수 있는 기능
setViewfinder()
이 포함되어 있습니다. setViewfinder()
의 지원되는 매개변수에는 QVideoWidget
, QGraphicsVideoItem
및 QAbstractVideoSurface
가 포함됩니다.내 목표는 바코드 감지를 위해 웹캠에서 미리보기 프레임을 얻는 것입니다. 따라서
QAbstractVideoSurface
클래스를 서브클래싱하고 present()
메서드에서 프레임 데이터를 가져와야 합니다.myvideosurface.h
파일을 만듭니다.#ifndef MYVIDEOSURFACE_H
#define MYVIDEOSURFACE_H
#include <QImage>
#include <QPixmap>
#include <QDebug>
#include <QCamera>
#include <QCameraInfo>
#include <QAbstractVideoSurface>
#include <QLabel>
#include <QDateTime>
#include "DynamsoftCommon.h"
#include "DynamsoftBarcodeReader.h"
QT_BEGIN_NAMESPACE
namespace Ui
{
class MainWindow;
}
QT_END_NAMESPACE
class MyVideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
private:
Ui::MainWindow *ui;
void *reader;
bool is_detecting;
public:
MyVideoSurface(QObject *parent, Ui::MainWindow *ui, void *reader);
~MyVideoSurface();
void reset();
QList<QVideoFrame::PixelFormat>
supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const;
bool present(const QVideoFrame &frame);
};
#endif // MYVIDEOSURFACE_H
MyVideoSurface
클래스의 생성자는 QObject
포인터, Ui::MainWindow
포인터 및 void
포인터를 사용합니다. Ui::MainWindow
포인터는 모든 UI 위젯에 액세스하는 데 사용됩니다. void *reader
포인터는 바코드를 감지하는 데 사용됩니다.다음으로
MyVideoSurface.cpp
클래스의 구현을 추가하기 위해 MyVideoSurface
파일을 생성합니다.supportedPixelFormats()
는 웹캠의 지원되는 픽셀 형식을 가져오는 것입니다. 어떤 형식을 사용해야 합니까? 솔직히 모르겠습니다. 처음에는 QVideoFrame::Format_RGB24
를 사용했는데 제 웹캠에서 QVideoFrame::Format_RGB24
가 지원되지 않는 것 같습니다. 오류 메시지에 따르면 대신 QVideoFrame::Format_ARGB32
를 사용합니다.QList<QVideoFrame::PixelFormat> MyVideoSurface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
{
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_RGB32;
}
present()
함수에서는 QVideoFrame
개체에서 프레임 데이터를 가져와 QImage
개체로 변환합니다.bool MyVideoSurface::present(const QVideoFrame &frame)
{
if (frame.isValid() && is_detecting)
{
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
const QImage img(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame.pixelFormat()));
cloneFrame.unmap();
return true;
}
return false;
}
미리보기 프레임을 표시하려면 프레임 데이터의 복사본을 만들어야 합니다.
QImage cp = img.copy();
제 경우에는
QVideoFrame
개체에서 가져온 이미지가 세로로 반전되어 있습니다. QImage::mirrored()
기능으로 이미지를 뒤집을 수 있습니다.cp = cp.mirrored(false, true);
그런 다음
DBR_DecodeBuffer()
를 호출하여 프레임에서 바코드를 감지하고 이미지에 경계 상자를 그립니다.int ret = DBR_DecodeBuffer(reader, (unsigned char *)cp.bits(), cp.width(), cp.height(), cp.bytesPerLine(), IPF_ARGB_8888, "");
DBR_GetAllTextResults(reader, &handler);
QPixmap pm = QPixmap::fromImage(cp);
QPainter painter(&pm);
painter.setPen(Qt::red);
QString out = "";
TextResult **results = handler->results;
for (int index = 0; index < handler->resultsCount; index++)
{
LocalizationResult* localizationResult = results[index]->localizationResult;
out += "Index: " + QString::number(index) + ", Elapsed time: " + QString::number(start.msecsTo(end)) + "ms\n";
out += "Barcode format: " + QString(results[index]->barcodeFormatString) + "\n";
out += "Barcode value: " + QString(results[index]->barcodeText) + "\n";
out += "Bounding box: (" + QString::number(localizationResult->x1) + ", " + QString::number(localizationResult->y1) + ") "
+ "(" + QString::number(localizationResult->x2) + ", " + QString::number(localizationResult->y2) + ") "
+ "(" + QString::number(localizationResult->x3) + ", " + QString::number(localizationResult->y3) + ") "
+ "(" + QString::number(localizationResult->x4) + ", " + QString::number(localizationResult->y4) + ")\n";
out += "----------------------------------------------------------------------------------------\n";
painter.drawLine(localizationResult->x1, localizationResult->y1, localizationResult->x2, localizationResult->y2);
painter.drawLine(localizationResult->x2, localizationResult->y2, localizationResult->x3, localizationResult->y3);
painter.drawLine(localizationResult->x3, localizationResult->y3, localizationResult->x4, localizationResult->y4);
painter.drawLine(localizationResult->x4, localizationResult->y4, localizationResult->x1, localizationResult->y1);
}
DBR_FreeTextResults(&handler);
painter.end();
마지막으로 레이블에 이미지를 표시하고 텍스트 상자에 바코드 인식 결과를 표시합니다.
ui->label->setPixmap(pm.scaled(ui->label->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
ui->textEdit_results->setText(out);
지금까지
myvideosurface
부분이 완료되었습니다. mainwindow.cpp
로 이동하여 카메라 제어 논리에 대한 코드를 추가할 수 있습니다.Qt Creator에서
mainwindow.ui
를 열고 카메라 제어 버튼을 추가합니다.MainWindow
생성자에서 카메라 상태를 확인하고 카메라 객체와 표면 객체를 초기화합니다.QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
if (cameras.size() > 0)
{
for( int i = 0; i < cameras.count(); ++i )
{
QCameraInfo cameraInfo = cameras.at(i);
qDebug() << cameraInfo.deviceName();
qDebug() << cameraInfo.description();
camera = new QCamera(cameraInfo);
surface = new MyVideoSurface(this, ui, reader);
camera->setViewfinder(surface);
break;
}
}
else {
ui->pushButton_open->setEnabled(false);
ui->pushButton_stop->setEnabled(false);
}
그런 다음 버튼 클릭 이벤트를 해당 기능에 바인딩합니다.
connect(ui->pushButton_open, SIGNAL(clicked()), this, SLOT(startCamera()));
connect(ui->pushButton_stop, SIGNAL(clicked()), this, SLOT(stopCamera()));
void MainWindow::startCamera()
{
surface->reset();
camera->start();
}
void MainWindow::stopCamera()
{
camera->stop();
}
바코드 스캐너를 사용할 준비가 되었습니다. 애플리케이션을 빌드하고 실행해 보겠습니다.
mkdir build
cd build
cmake -G "MinGW Makefiles" ..
cmake --build .
BarcodeReader.exe
소스 코드
https://github.com/yushulx/Qt-desktop-barcode-reader
Reference
이 문제에 관하여(Qt QCamera를 사용하여 웹캠으로 바코드 스캐너를 구현하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/yushulx/how-to-implement-barcode-scanner-with-webcam-using-qt-qcamera-3nf3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)