openCV_qr코드 라벨링 및 여러 각도에서 인식 - chloe73/openCV GitHub Wiki

💡필요한 알고리즘

  1. 이미지 변환
  2. 라벨링

Find Pattern: 오른쪽 / 왼쪽 상단 , 왼쪽 하단 모서리 3by3 , 5by5 , 7by7의 상자로 둘러싸져 있는 네모상자로 이 패턴으로 360도에서 인식이 가능하다.

  1. 이미지 불러오기

  2. 이미지 그레이스케일 1채널로 변경

  3. 이미지 변환으로 이미지 정상화하기

  4. 라벨링으로

훼손이라면 : 복구하고 Find Pattern 라벨링하기

라벨링 했는데 만약 find pattern이 각 위치에 안가있다면 회전시켜주기

훼손인지 아닌지 판별?

  1. 훼손 복구
  2. find pattern 라벨링

회전을 해야하는지 안해야하는지 판별?

  1. 라벨링한것을 base로 회전

💡QR코드 찾기

방법1

  1. 파인더 패턴 추출 불가능시 수신된 QR코드 이미지와 저장된 각 각도별 QR코드 이미지의 유사도를 계산한다.
  2. 유사도가 가장 큰 QR코드 이미지를 추출한다.

QR 코드 이미지의 촬영 각도가 0 °라고 할 때, QR 코드 이미지 등록부 (121)는 상 / 하 및 / 우 각각 10 ° 간격으로 회전 된 QR 코드 이미지 (- 70 °, -60 °, -50 °, -40 °, -30 °, -20 °, -10 °, 0 °, 10 °, 20 °, 30 °, 40 °, 50 °, 60 °, 70 ° )를 생성 할 수있다

방법2.

  • 반대로 우측 하단에 findpattern이 없는 것을 찾자.

파인더 패턴 추출

ee

✅QR코드 인식

💡이미지 라벨링을 통한 qr코드 사각형 구분하기

  • 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);
    }

    11


  • 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()

    22


💡QRCodeDetector 사용하여 qr코드 검출

#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;

}

33

⚠️ **GitHub.com Fallback** ⚠️