OpenCV-Python 다 중 템 플 릿 일치 실현
템 플 릿 매 칭 은 한 그림 에서 다른 템 플 릿 이미지 가 가장 일치 하 는 부분 을 찾 는 기술 입 니 다.
다 중 템 플 릿 일치
지난 실전 에서 우 리 는 인물 눈의 자 도 를 통 해 이미지 에 나타 난 위 치 를 찾 아 냈 다.그러나 어떤 경우 에 우리 가 푸 리 엽 의 변 화 를 설명 할 때 초원 의 사자 도 를 소개 한 적 이 있다.어떤 풀 과 일치 하면 하나의 그림 에 많은 것 이 있 을 수 있 으 며,이 럴 때 는 여러 개의 일치 하 는 결 과 를 찾 아야 한다.
함수 cv2.minMaxLoc()는 최대 값 만 찾 을 수 있 을 뿐 모든 일치 하 는 지역 의 위치 정 보 를 제공 할 수 없습니다.따라서 여러 결 과 를 일치 시 키 려 면 다음 과 같은 4 단계 가 필요 하 다.
일치 하 는 위치의 집합 가 져 오기
우선,Numpy 라 이브 러 리 의 함수 where()는 템 플 릿 이 일치 하 는 위치의 집합 을 가 져 올 수 있 습 니 다.입력 에 따라 반환 값 이 다 릅 니 다.
4.567917.입력 이 1 차원 배열 일 때 반환 값 은 1 차원 색인 이 고 색인 배열 일 뿐 입 니 다4.567917.입력 이 2 차원 배열 일 때 일치 하 는 위치 색인 을 되 돌려 주기 때문에 두 개의 색인 배열 은 반환 값 의 위 치 를 표시 합 니 다예 를 들 어 우리 의 그 레이스 케 일 이미 지 는 일반적으로 2 차원 배열 이다.다음은 2 차원 배열 에서 8 이상 의 요소 색인 을 찾 아 보 겠 습 니 다.
import numpy as np
img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
print(result)
실행 후 콘 솔 은 다음 과 같은 내용 을 출력 합 니 다.니 가 Numpy 에 대해 잘 모 르 면아래 블 로 거들 은 데 이 터 를 아래 로 바 꾸 면 기본적으로 모두 알 아 볼 수 있다.변환 후 형식 은 다음 과 같 습 니 다.
첫 번 째 행 위 는 5 의 값 보다 큰 X 좌표 이 고,두 번 째 행 위 는 5 의 값 보다 큰 Y 좌표 이다.그러면 위의 5 이상 의 배열 색인 은[0,2],[0,3],[0,4],[1,0],[1,1],[1,2],[1,3],[2,0],[2,1],[2,2],[2,3]이다.너 는 일치 하 는 지 돌 이 켜 볼 수 있다.
np.where()함 수 를 통 해 cv2.matchTemplate()함수 의 반환 값 에서 어떤 위치의 값 이 한도 값 threshold 보다 큰 지 찾 을 수 있 습 니 다.구체 적 인 조작 코드 는 다음 과 같다.
loc=np.where(res>threshold)
순환 하 다.우리 가 찾 은 원본 그림 에 대응 하 는 템 플 릿 그림 은 하나 가 아니 기 때문에 여러 값 을 처리 하려 면 반드시 순환 을 사용 할 것 입 니 다.따라서 일치 하 는 값 의 색인 을 가 져 온 후에 다음 과 같은 문 구 를 사용 하여 일치 하 는 모든 위 치 를 옮 겨 다 니 며 이 위 치 를 표시 할 수 있 습 니 다.
for i in :
순환 중 zip 사용()함수 zip()는 교체 가능 한 대상 을 매개 변수 로 하여 대상 에 대응 하 는 요 소 를 하나의 원 그룹 으로 포장 한 다음 에 이 원 그룹 으로 구 성 된 목록 을 되 돌려 줍 니 다.
예 를 들 어 우리 가 얻 은 색인 은 x,y,z 이다.다음은 zip()를 사용 하여 원 그룹 으로 포장 합 니 다.코드 는 다음 과 같 습 니 다:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
for i in zip(*result):
print(i)
여기 서 우 리 는 위의 값 을 사용 합 니 다.출력 결 과 는 다음 과 같 습 니 다.여기 서 우리 가 방금 조건 을 만족 시 킨 색인 을 요소 형식 으로 자동 으로 포장 합 니 다.아까 콘 솔 출력 결과 보다 더 직관 적 이지 않 나 요?
좌표 바 꾸 기
우리 가 위 에서 얻 은 결 과 는 조건 에 맞 는 색인 입 니 다.(줄 번호,열 번호)그러나 우 리 는 위치 에 맞 는 사각형 을 그 려 야 합 니 다.필요 한 것 은(열 번호,줄 번호)입 니 다.
따라서 cv2.rectangle()을 사용 하여 사각형 을 그리 기 전에 함수 numpy.where()가 얻 은 위치 색인 행렬 을 교환 해 야 합 니 다.행렬 교환 은 다음 코드 를 통 해 이 루어 질 수 있 습 니 다.
import numpy as np
img = np.array([[2, 4, 6, 8, 10], [9, 60, 10, 30, 4], [55, 21, 11, 7, 5]])
result = np.where(img > 5)
for i in zip(*result[::-1]):
print(i)
실행 후 출력 결 과 는 다음 과 같 습 니 다.실전 멀 티 템 플 릿 일치
여러 템 플 릿 의 위 치 를 표시 하 는 네 가지 절 차 를 알 았 으 니아래,우 리 는 위의 코드 를 아래 와 직접 정리 하면 다 중 템 플 릿 의 매 칭 을 완성 할 수 있 습 니 다.구체 적 인 코드 는 다음 과 같다.
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("34.jpg", 0)
template = cv2.imread("4_1.jpg", 0)
w, h = template.shape[::-1]
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.9
loc = np.where(res >= 0.9)
for i in zip(*loc[::-1]):
cv2.rectangle(img, i, (i[0] + w, i[1] + h), 255, 1)
plt.imshow(img, cmap="gray")
plt.axis("off")
plt.show()
이곳 의 코드 는 위의 4 단계 와 마찬가지 로 구체 적 으로 너무 많은 설명 을 하지 않 는 다.실행 하면 여러 템 플 릿 이 일치 합 니 다.부록:
템 플 릿
원 도
인 스 턴 스:opencv 기반 다 중 목표 템 플 릿 일치
opencv 를 이용 하여 다 중 목표 템 플 릿 매 칭 을 진행 합 니 다.matchTemplate 함 수 를 이용 하 는 것 이 라면 다 중 목표(여 기 는 목표 그림 의 크기 별 템 플 릿 매 칭 을 토론 합 니 다)에 코드 와 그림 을 붙 여 참고 하 시기 바 랍 니 다.
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
Point getNextMinLoc(Mat &result, Point minLoc, int maxValue, int templatW, int templatH);
int main(void)
{
Mat src = imread("1_2.png");
Mat srcCopy = src.clone();
Mat temp = imread("1_4.png");
Mat result;
if (src.empty() || temp.empty())
{
cout << " " << endl;
return 0;
}
vector<Mat> templat;
vector<float> minV;
vector<Point> minL;
int srcW, srcH, templatW, templatH, resultH, resultW;
srcW = src.cols;
srcH = src.rows;
templat.push_back(temp);
double minValue, maxValue;
Point minLoc, maxLoc;
for (int i=0;i<10;i++)
{
cout << i << ": ";
templatW = templat[i].cols;
templatH = templat[i].rows;
if (srcW < templatW || srcH < templatH)
{
cout << " " << endl;
return 0;
}
resultW = srcW - templatW + 1;
resultH = srcH - templatH + 1;
result.create(Size(resultW, resultH), CV_32FC1);
matchTemplate(src, templat[i], result, CV_TM_SQDIFF_NORMED);
minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);
cout << "min1: " << minValue << endl;
if (minValue<=0.070055)
{
rectangle(srcCopy, minLoc, Point(minLoc.x + templatW, minLoc.y + templatH), Scalar(0, 0, 255), 2, 8, 0);
Point new_minLoc;
new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH);
float *data = result.ptr<float>(new_minLoc.y);
cout << "min2: " << data[new_minLoc.x] << " ";
if (data[new_minLoc.x]<=0.5)
{
cout << " :" << i << ":" << new_minLoc.x;
cout << " " << new_minLoc.y;
rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
Scalar(0, 255, 0), 2, 8, 0);
new_minLoc = getNextMinLoc(result, new_minLoc, maxValue, templatW, templatH);
}
float *data1 = result.ptr<float>(new_minLoc.y);
cout << "min3: " << data1[new_minLoc.x] << " " << endl;
if (data1[new_minLoc.x] <= 0.4)
{
rectangle(srcCopy, new_minLoc, Point(new_minLoc.x + templatW, new_minLoc.y + templatH),
Scalar(255, 0, 0), 2, 8, 0);
}
}
cout << "#" << endl;
Mat temp_templat;
resize(templat[i], temp_templat, Size(templat[i].cols / 1.1, templat[i].rows / 1.1));
templat.push_back(temp_templat);
}
imshow(" ", srcCopy);
waitKey(0);
return 0;
}
Point getNextMinLoc(Mat &result, Point minLoc, int maxValue, int templatW, int templatH)
{
//imshow("result", result);
//cout << "maxvalue: " << maxValue << endl;
int startX = minLoc.x - templatW / 3;
int startY = minLoc.y - templatH / 3;
int endX = minLoc.x + templatW / 3;
int endY = minLoc.y + templatH / 3;
if (startX < 0 || startY < 0)
{
startX = 0;
startY = 0;
}
if (endX > result.cols - 1 || endY > result.rows - 1)
{
endX = result.cols - 1;
endY = result.rows - 1;
}
int y, x;
for (y = startY; y < endY; y++)
{
for (x = startX; x < endX; x++)
{
float *data = result.ptr<float>(y);
data[x] = maxValue;
}
}
double new_minValue, new_maxValue;
Point new_minLoc, new_maxLoc;
minMaxLoc(result, &new_minValue, &new_maxValue, &new_minLoc, &new_maxLoc);
//imshow("result_end", result);
return new_minLoc;
}
다음은 결과 그림 입 니 다.
여기 서 OpenCV-Python 이 다 중 템 플 릿 매 칭 을 실현 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 OpenCV 다 중 템 플 릿 매 칭 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Visual Studio 2017에서 OpenCV 템플릿 프로젝트 만들기・Windows 7 Professional 64bit ・Visual Studio 2017 Version 15.9.14 · OpenCV 3.4.1 OpenCV의 도입 방법 등은 아래를 참조하십시오. Visual Stu...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.