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 다 중 템 플 릿 매 칭 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기