欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OpenCV-Python實現(xiàn)多模板匹配

 更新時間:2021年06月08日 11:43:45   作者:一天一篇Python庫  
模板匹配就是在一幅圖像中尋找另一幅模板圖像最匹配,本文主要實現(xiàn)了多模板匹配,具有一定的參考價值,感興趣的小伙伴們可以參考一下

模板匹配的作用在圖像識別領域作用可大了。那什么是模板匹配?

模板匹配,就是在一幅圖像中尋找另一幅模板圖像最匹配(也就是最相似)的部分的技術。

多模板匹配

在上一篇的實戰(zhàn)中,我們通過人物眼睛的子圖,找出了其在圖像中出現(xiàn)位置。但是,有些情況下,并不僅僅只有一次,比如我們講解傅里葉變換時,曾介紹一張草原的獅子圖。如果匹配某個草,可能單個圖像內會有很多,這個時候就要找出多個匹配結果。

而函數cv2.minMaxLoc()僅僅能找出最值,無法給出所有匹配區(qū)域的位置信息。所以,要想匹配多個結果,就需要進行如下4個步驟:

獲取匹配位置的集合

首先,Numpy庫中的函數where()能夠獲取模板匹配位置的集合。對于不同的輸入,其返回值是不同的。

  • 當輸入是一維數組時,返回值是一維索引,只是一組索引數組。
  • 當輸入是二維數組時,返回的是匹配值的位置索引,因此會有兩組索引數組表示返回值的位置。

比如,我們的灰度圖像一般都是二維數組。下面,我們來查找一個二維數組中,值大于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)

循環(huán)

因為我們找到的原圖對應的模板圖像不止一個,要處理多個值,肯定會用到循環(huán)。因此,在獲取匹配值的索引后,可以采用如下語句遍歷所有匹配的位置,對這些位置做標記:

for i in 匹配位置集合:
	標記匹配位置

在循環(huán)中使用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()得到的位置索引行列互換,行列互換可以通過如下代碼實現(xiàn):

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)

運行之后,輸出結果如下:

行列互換

實戰(zhàn)多模板匹配

既然我們已經了解了標記繪制多個模板位置的4個步驟。下面,我們直接將上面的代碼整理以下,即可完成多模板的匹配。具體代碼如下所示:

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實現(xiàn)多模板匹配的文章就介紹到這了,更多相關OpenCV 多模板匹配內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring http服務遠程調用實現(xiàn)過程解析

    Spring http服務遠程調用實現(xiàn)過程解析

    這篇文章主要介紹了Spring http服務遠程調用實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Python?ftfy?包的使用案例解析

    Python?ftfy?包的使用案例解析

    Unicode是一種字符編碼標準,用于表示文本中的字符,通過安裝 ftfy 軟件包,可以在 Python 中使用它提供的函數和工具來處理和修復文本中的 Unicode 問題,從而確保文本在各種應用中的正確性和可靠性,這篇文章主要介紹了Python ftfy包的理解和使用,需要的朋友可以參考下
    2023-05-05
  • pytorch訓練時的顯存占用遞增的問題解決

    pytorch訓練時的顯存占用遞增的問題解決

    本文主要介紹了pytorch訓練時的顯存占用遞增的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • 詳解python之多進程和進程池(Processing庫)

    詳解python之多進程和進程池(Processing庫)

    本篇文章主要介紹了詳解python之多進程和進程池(Processing庫),非常具有實用價值,需要的朋友可以參考下
    2017-06-06
  • Python腳本實現(xiàn)下載合并SAE日志

    Python腳本實現(xiàn)下載合并SAE日志

    這篇文章主要介紹了Python腳本實現(xiàn)下載合并SAE日志,本文講解了代碼編寫過程,然后給出了完整代碼,需要的朋友可以參考下
    2015-02-02
  • python XlsxWriter模塊創(chuàng)建aexcel表格的實例講解

    python XlsxWriter模塊創(chuàng)建aexcel表格的實例講解

    今天小編就為大家分享一篇python XlsxWriter模塊創(chuàng)建aexcel表格的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Python爬蟲之Selenium實現(xiàn)關閉瀏覽器

    Python爬蟲之Selenium實現(xiàn)關閉瀏覽器

    這篇文章主要介紹了Python爬蟲之Selenium實現(xiàn)關閉瀏覽器,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • python?包中的sched?事件調度器的操作方法

    python?包中的sched?事件調度器的操作方法

    sched模塊內容很簡單,只定義了一個類。它用來最為一個通用的事件調度模塊,接下來通過本文給大家介紹python?包之?sched?事件調度器教程,需要的朋友可以參考下
    2022-04-04
  • python如何實現(xiàn)一個刷網頁小程序

    python如何實現(xiàn)一個刷網頁小程序

    這篇文章主要給大家介紹了關于利用python如何實現(xiàn)一個刷網頁小程序的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • python基礎知識之try...except...的詳細用法實例

    python基礎知識之try...except...的詳細用法實例

    在各種編程語言進行工作和學習的過程中,都會有一些錯誤異常,下面這篇文章主要給大家介紹了關于python基礎知識之try...except...的詳細用法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-08-08

最新評論