이번 글에서는 QR코드를 만드는 방법에 대해 알아보겠습니다.
QR코드 생성과 관련해서는 여러 라이브러리가 있지만 이 글에서는 QR Code generator를 사용하겠습니다.
여기에서 파일을 다운 받아 줍니다
cpp 폴더에 파일명이 qrcodegen인 hpp와 cpp파일을 프로젝트에 복사해 추가해줍니다.
QR Code generator를 사용하기 위해 코드에 qrcodegen.hpp을 include 해줍니다.
#include "qrcodegen.hpp"
using qrcodegen::QrCode;
라이브러리에서 제공해주는 QR Code 클래스 명칭은 QrCode 입니다. QrCode 클래스의 encodeText 멤버 함수를 사용하면 쉽게 QR코드를 생성할 수 있습니다.
const QrCode qr = QrCode::encodeText("https://3001ssw.tistory.com", QrCode::Ecc::LOW);
첫번째 인자는 QR코드에 들어갈 텍스트, 두번째 인자는 오류복원 레벨입니다.
참고로 오류복원 레벨은 QR Code 이미지가 훼손되더라도 데이터를 복구 할 수 있는 기능을 말하며, 레벨을 높이면 코드의 크기가 커집니다.
어쨌든 encodeText 함수를 수행하며 QrCode 객체를 반환받았습니다.
이 QrCode 객체를 Mat 객체로로 변환하기 위해서 MakeQrCodeMat 함수를 선언해줍니다.
Mat MakeQrCodeMat(const QrCode &qr, int iBorder = 0);
첫번째 인자는 입력 QrCode 객체, 두번째 인자는 테두리 입니다.
QR Code 이미지에 테두리를 넣으려면 iBorder에 값을 입력하면 됩니다.
MakeQrCodeMat 함수 정의는 아래와 같습니다.
Mat MakeQrCodeMat(const QrCode &qr, int iBorder/* = 0*/)
{
int iQrSize = qr.getSize();
int iNewSize = iQrSize + iBorder*2;
Mat img(iNewSize, iNewSize, CV_8UC1, Scalar(255));
for (int iQrPosX = 0; iQrPosX < iQrSize; iQrPosX++)
{
for (int iQrPosY = 0; iQrPosY < iQrSize; iQrPosY++)
{
if (qr.getModule(iQrPosX, iQrPosY))
{
int iNewX = iQrPosX + iBorder;
int iNewY = iQrPosY + iBorder;
img.at<uchar>(iNewY, iNewX) = 0;
}
}
}
return img;
}
main 함수에 아래와 같이 입력해줍니다.
const QrCode qr = QrCode::encodeText("https://3001ssw.tistory.com", QrCode::Ecc::LOW); // 텍스트, 오류복원 레벨
Mat img = MakeQrCodeMat(qr, 2); // QrCode => Mat
imshow("img", img);
waitKey();
destroyAllWindows();
실행 결과는 아래와 같습니다.
QR Code 이미지가 너무 작습니다. 이미지가 너무 작으면 인식이 안되므로 이럴땐 OpenCV에서 제공하는 resize 함수를 사용하면 편하게 사이즈 조절이 가능합니다.
const QrCode qr = QrCode::encodeText("https://3001ssw.tistory.com", QrCode::Ecc::LOW); // 텍스트, 오류복원 레벨
Mat img = MakeQrCodeMat(qr, 2); // QrCode => Mat
Mat img_resize;
resize(img, img_resize, Size(300, 300), 0, 0, INTER_NEAREST); // 사이즈 변환
imshow("img", img);
imshow("img_resize", img_resize);
waitKey();
destroyAllWindows();
다시 실행하여 확인해봅니다.
사이즈가 넓어진 것을 볼 수 있습니다.
전체 코드입니다.
#include <iostream>
#include "opencv2/opencv.hpp"
#ifdef _DEBUG
#pragma comment(lib, "opencv_world451d.lib")
#else
#pragma comment(lib, "opencv_world451.lib")
#endif
#include "qrcodegen.hpp"
#include "Windows.h"
using namespace std;
using namespace cv;
using qrcodegen::QrCode;
using namespace qrcodegen;
// QrCode => Mat
Mat MakeQrCodeMat(const QrCode &qr, int iBorder = 0);
void DetectQrCode(Mat src);
int main()
{
const QrCode qr = QrCode::encodeText("https://3001ssw.tistory.com", QrCode::Ecc::LOW); // 텍스트, 오류복원 레벨
Mat img = MakeQrCodeMat(qr, 2); // QrCode => Mat
Mat img_resize;
resize(img, img_resize, Size(300, 300), 0, 0, INTER_NEAREST); // 사이즈 변환
imshow("img", img);
imshow("img_resize", img_resize);
waitKey();
destroyAllWindows();
return 0;
}
Mat MakeQrCodeMat(const QrCode &qr, int iBorder/* = 0*/)
{
int iQrSize = qr.getSize();
int iNewSize = iQrSize + iBorder*2;
Mat img(iNewSize, iNewSize, CV_8UC1, Scalar(255));
for (int iQrPosX = 0; iQrPosX < iQrSize; iQrPosX++)
{
for (int iQrPosY = 0; iQrPosY < iQrSize; iQrPosY++)
{
if (qr.getModule(iQrPosX, iQrPosY))
{
int iNewX = iQrPosX + iBorder;
int iNewY = iQrPosY + iBorder;
img.at<uchar>(iNewY, iNewX) = 0;
}
}
}
return img;
}
이상으로 QR코드 생성에 대해 알아보았습니다.