openCV_qr코드 라벨링 및 여러 각도에서 인식 - chloe73/openCV GitHub Wiki
- 이미지 변환
- 라벨링
Find Pattern: 오른쪽 / 왼쪽 상단 , 왼쪽 하단 모서리 3by3 , 5by5 , 7by7의 상자로 둘러싸져 있는 네모상자로 이 패턴으로 360도에서 인식이 가능하다.
-
이미지 불러오기
-
이미지 그레이스케일 1채널로 변경
-
이미지 변환으로 이미지 정상화하기
-
라벨링으로
훼손이라면 : 복구하고 Find Pattern 라벨링하기
라벨링 했는데 만약 find pattern이 각 위치에 안가있다면 회전시켜주기
훼손인지 아닌지 판별?
- 훼손 복구
- find pattern 라벨링
회전을 해야하는지 안해야하는지 판별?
- 라벨링한것을 base로 회전
- 파인더 패턴 추출 불가능시 수신된 QR코드 이미지와 저장된 각 각도별 QR코드 이미지의 유사도를 계산한다.
- 유사도가 가장 큰 QR코드 이미지를 추출한다.
QR 코드 이미지의 촬영 각도가 0 °라고 할 때, QR 코드 이미지 등록부 (121)는 상 / 하 및 / 우 각각 10 ° 간격으로 회전 된 QR 코드 이미지 (- 70 °, -60 °, -50 °, -40 °, -30 °, -20 °, -10 °, 0 °, 10 °, 20 °, 30 °, 40 °, 50 °, 60 °, 70 ° )를 생성 할 수있다
- 반대로 우측 하단에 findpattern이 없는 것을 찾자.
-
C++ 코드
#include <iostream> #include <opencv2/core/mat.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> using namespace cv; using namespace std; int main() { Mat img_gray, img_color, img_binary; img_gray = imread("QRImage.png", IMREAD_GRAYSCALE); threshold(img_gray, img_binary, 127, 255, THRESH_BINARY); cvtColor(img_gray, img_color, COLOR_GRAY2BGR); Mat img_labels, stats, centroids; int numOfLables = connectedComponentsWithStats(img_binary, img_labels, stats, centroids, 8, CV_32S); //라벨링된 이미지중 특정 라벨을 컬러로 표현해주기 for (int y = 0; y < img_labels.rows; ++y) { int* label = img_labels.ptr<int>(y); Vec3b* pixel = img_color.ptr<Vec3b>(y); for (int x = 0; x < img_labels.cols; ++x) { if (label[x] == 3) { pixel[x][2] = 0; pixel[x][1] = 255; pixel[x][0] = 0; } } } //라벨링 된 이미지에 각각 직사각형으로 둘러싸기 for (int j = 1; j < numOfLables; j++) { int area = stats.at<int>(j, CC_STAT_AREA); int left = stats.at<int>(j, CC_STAT_LEFT); int top = stats.at<int>(j, CC_STAT_TOP); int width = stats.at<int>(j, CC_STAT_WIDTH); int height = stats.at<int>(j, CC_STAT_HEIGHT); rectangle(img_color, Point(left, top), Point(left + width, top + height), Scalar(0, 0, 255), 1); putText(img_color, to_string(j), Point(left + 20, top + 20), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 0), 2); } imshow("result", img_color); waitKey(0); }
-
python 코드
import sys import numpy as np import cv2 import matplotlib.pyplot as plt img = "resource/QRImage.png" # 파일 위치 저장 src = cv2.imread(img, cv2.IMREAD_GRAYSCALE) resize_img = cv2.resize(src, (500,500)) # 이미지 크기 조절 if resize_img is None: print('Image load failed!') sys.exit() _, src_bin = cv2.threshold(resize_img, 0, 255, cv2.THRESH_OTSU) cnt, labels, stats, centroids = cv2.connectedComponentsWithStats(src_bin) dst = cv2.cvtColor(resize_img, cv2.COLOR_GRAY2BGR) for i in range(1, cnt): # 각각의 객체 정보에 들어가기 위해 반복문. 범위를 1부터 시작한 이유는 배경을 제외 (x, y, w, h, area) = stats[i] # 노이즈 제거 if area < 20: continue cv2.rectangle(dst, (x, y, w, h), (0, 255, 255)) cv2.imshow('src', resize_img) cv2.imshow('src_bin', src_bin) cv2.imshow('dst', dst) cv2.waitKey() cv2.destroyAllWindows()
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void decode_qrcode() {
Mat src = imread("qrcode.png");
Mat resized_image;
resize(src, resized_image, Size(400, 400));
if (resized_image.empty()) {
cerr << "IMAGE LOAD FAILED!" << endl;
return;
}
QRCodeDetector detector;
vector<Point> points;
String info = detector.detectAndDecode(resized_image, points);
if (!info.empty()) {
polylines(resized_image, points, true, Scalar(0, 0, 255), 2);
putText(resized_image, info, Point(10, 40), FONT_HERSHEY_DUPLEX, 0.5,
Scalar(0, 0, 255));
}
string site = "explorer " + info;
//system(site.c_str());
imshow("src", resized_image);
waitKey(0);
destroyAllWindows();
}
int main(void) {
decode_qrcode();
return 0;
}