<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
目錄結構
開始定義我們的 ShapeDetector 類。我們將跳過這裡的 init 建構函式,因為不需要初始化任何東西。
# 匯入必要的包 import cv2 class ShapeDetector: def __init__(self): pass def detect(self, c): # 初始化形狀名稱並近似輪廓 shape = "unidentified" peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.04 * peri, True)
我們的檢測方法,它只需要一個引數 c,即我們試圖識別的形狀的輪廓。為了進行形狀檢測,我們將使用輪廓逼近。
顧名思義,輪廓近似是一種演演算法,用於減少曲線中點的數量,並減少點集——因此稱為近似。
輪廓近似是基於曲線可以由一系列短線段近似的假設。這導致生成的近似曲線由原始曲線定義的點的子集組成。
輪廓近似實際上已經在 OpenCV 中通過 cv2.approxPolyDP 方法實現。
為了進行輪廓逼近,我們首先計算輪廓的周長,然後構建實際的輪廓逼近。 cv2.approxPolyDP 的第二個引數的常用值通常在原始輪廓周長的 1%-5% 範圍內。
給定我們的近似輪廓,我們可以繼續執行形狀檢測:
# 如果形狀是一個三角形,它將有3個頂點 if len(approx) == 3: shape = "triangle" # 如果形狀有4個頂點,它要麼是正方形,要麼是矩形 elif len(approx) == 4: # 計算輪廓的包圍框,並使用包圍框計算高寬比 (x, y, w, h) = cv2.boundingRect(approx) ar = w / float(h) # 正方形的長寬比大約等於1,否則,形狀就是矩形 shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle" # 如果形狀是一個五邊形,它將有5個頂點 elif len(approx) == 5: shape = "pentagon" # 否則,我們假設形狀是一個圓 else: shape = "circle" # 返回形狀的名稱 return shape
重要的是要了解輪廓由頂點列表組成。我們可以檢查此列表中的數目以確定物件的形狀。例如,如果近似輪廓有三個頂點
那麼它一定是一個三角形。如果一條輪廓有四個頂點,那麼它一定是正方形或矩形。為了確定這一點,我們計算形狀的長寬比
也就是輪廓邊界框的寬度除以高度。如果長寬比是~1.0,那麼我們正在檢查一個正方形(因為所有的邊都有大約相等的長度)。否則,形狀就是矩形。如果一條等高線有五個頂點,我們可以將其標記為五邊形。否則,我們可以假設我們正在檢查的形狀是一個圓。
最後,將標識好的形狀返回給呼叫方法。
我們已經定義了一個utils模組。在這個模組中,我們有shapedetector .py,它將儲存ShapeDetector類的實現。
最後,我們有detect_shapes.py指令碼,我們將使用它從磁碟載入影象,分析它的形狀,然後通過ShapeDetector類執行形狀檢測和識別。
現在我們的 ShapeDetector 類已經定義好了,讓我們建立 detect_shapes.py 指令碼:
# 匯入必要的庫 from utils.shapedetector import ShapeDetector import argparse import imutils import cv2 # 構造引數解析並解析引數 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", default="inpaint.jpg", help="path to the input image") args = vars(ap.parse_args())
首先匯入我們已經實現的ShapeDetector類,然後解析引數,下一步,我們開始預處理我們的影象
# 載入影象並將其調整影象大小,以便更好地近似形狀 image = cv2.imread(args["image"]) resized = imutils.resize(image, width=300) ratio = image.shape[0] / float(resized.shape[0]) # 將調整後的影象轉換為灰度,稍微模糊它,並閾值化 gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] # 在閾值化影象中找到輪廓並初始化形狀檢測器 cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) sd = ShapeDetector()
首先,我們從磁碟載入影象,並調整其大小。然後,我們跟蹤舊高度與調整後的新高度的比率——我們將在本教學的後面部分找到這樣做的確切原因。
將調整大小後的影象轉換為灰度,平滑它以減少高頻噪聲,最後閾值化它以顯示影象中的形狀。
閾值之後,我們的影象應該是這樣的:
請注意我們的影象是如何被二值化的——形狀顯示為黑色背景下的白色前景。
最後,在二值影象中找到輪廓,基於OpenCV版本的cv2.findContours獲取正確的元組值,並最終初始化我們的ShapeDetector。
最後一步是識別每個輪廓:
# 遍歷所有輪廓 for c in cnts: # 計算輪廓的中心,然後僅使用輪廓檢測形狀的名稱 M = cv2.moments(c) cX = int((M["m10"] / M["m00"]) * ratio) cY = int((M["m01"] / M["m00"]) * ratio) shape = sd.detect(c) # 將輪廓(x, y)座標乘以調整比例,然後在影象上繪製輪廓和形狀的名稱 c = c.astype("float") c *= ratio c = c.astype("int") cv2.drawContours(image, [c], -1, (0, 255, 0), 2) cv2.putText(image, shape, (cX, cY), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2) # 顯示輸出影象 cv2.imshow("Image", image) cv2.waitKey(0)
我們開始在每個單獨的輪廓上回圈。對於每一個,我們計算輪廓的中心,然後執行形狀檢測和識別。
由於我們正在處理從調整大小後的影象中提取的輪廓(而不是原始影象),我們需要將輪廓和中心(x, y)座標乘以調整比率。
這將為我們提供原始影象的輪廓和質心的正確(x, y)座標。
最後,我們在影象上繪製輪廓和識別的形狀,然後顯示我們的結果。
在本教學中,讓我們看看如何使用 OpenCV 的輪廓來識別物件的形狀和位置。
使用OpenCV的輪廓,你可以得到每個白斑的頂點的點序列(白斑被認為是多邊形)。例如,對於三角形你會得到3個點(頂點),
對於四邊形你會得到4個點。你可以通過多邊形的頂點數來識別任何多邊形。
你甚至可以通過計算和比較頂點之間的距離來識別多邊形的特徵,如凸性、凹性、等邊等。
我們看看如何使用 OpenCV 來完成。您所需要的只是一個二進位制影象,其中您的物件應該是白色的,背景應該是黑色的。
現在我將使用OpenCV C++應用程式來識別上圖中的三角形、四邊形和七邊形。我將沿著每個確定的多邊形的周長畫一條線,
三角形顏色為藍色,四邊形顏色為綠色,七邊形顏色為紅色。
#include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { Mat img = imread("FindingContours.png"); //show the original image namedWindow("Raw"); imshow("Raw", img); //converting the original image into grayscale Mat imgGrayScale = Mat(img.size(), CV_8UC1); cvtColor(img, imgGrayScale, COLOR_BGR2GRAY); //thresholding the grayscale image to get better results threshold(imgGrayScale, imgGrayScale, 128, 255, THRESH_BINARY); //finding all contours in the image vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(imgGrayScale, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); //iterating through each contour for (size_t i = 0; i < contours.size(); i++) { vector<Point> approx; //obtain a sequence of points of contour, pointed by the variable 'contour' approxPolyDP(contours[i], approx, arcLength(contours[i], true) * 0.02, true); //if there are 3 vertices in the contour(It should be a triangle) if (approx.size() == 3) { //drawing lines around the triangle for (int i = 0; i < 3; i++) { line(img, approx[i], approx[(i+1)%3], Scalar(255, 0, 0), 4); } } //if there are 4 vertices in the contour(It should be a quadrilateral) else if (approx.size() == 4) { //drawing lines around the quadrilateral for (int i = 0; i < 4; i++) { line(img, approx[i], approx[(i + 1) % 4], Scalar(0, 255, 0), 4); } } //if there are 7 vertices in the contour(It should be a heptagon) else if (approx.size() == 7) { //drawing lines around the heptagon for (int i = 0; i < 7; i++) { line(img, approx[i], approx[(i + 1) % 7], Scalar(0, 0, 255), 4); } } } //show the image in which identified shapes are marked namedWindow("Tracked"); imshow("Tracked", img); waitKey(0); //wait for a key press //cleaning up destroyAllWindows(); return 0; }
如您所見,三角形用藍色標記, 四邊形用綠色標記,七邊形用紅色標記。所以,現在很明顯,這種方法能夠識別形狀。 首先將原始影象轉換為灰度。
這是因為這種方法只適用於單通道的灰度影象。為了獲得更好的結果,我使用“threshold”函數對灰度影象進行閾值處理。
您可以使用自己的方式對影象進行閾值處理。然後我找到閾值影象中的所有輪廓,並識別和跟蹤所有三角形、四邊形和七邊形。
讓我們討論一下這個應用程式中的OpenCV 函數。
double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type);
src:源影象(8位元單通道)
dst:與src具有相同大小相同型別的目標影象
thresh:閾值
maxval:滿足條件的畫素替換為這個值
type:閾值化方法,
THRESH_BINARY
THRESH_BINARY_INV
THRESH_TOZERO
THRESH_TOZERO_INV
THRESH_TRUNC
在上面的應用程式中,我使用了“ THRESH_BINARY”,因為我想在物件所在的位置分配 255(白色其他是0(黑色)。
findContours( InputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point());
image: 8位元單通道影象。非零畫素被視為1。零畫素保持為0,因此影象被視為二值。你可以使用#compare #inRange #threshold,#adaptiveThreshold,
#Canny,以及其他引數來建立灰度或彩色影象的二值影象。
contours: 發現的所有輪廓
hierarchy:輪廓之間的層次結構
int mode - 從影象中檢索輪廓的模式,您必須選擇以下之一
int method - 近似方法,您必須選擇以下之一
Point offset:每個輪廓點應移動的偏移量。當我們在影象中設定 ROI(感興趣區域)時,這很有用。通常我們將偏移量設定為 ‘Point(0,0)’
void approxPolyDP( InputArray curve, OutputArray approxCurve, double epsilon, bool closed );
以上就是OpenCV形狀檢測的範例詳解的詳細內容,更多關於OpenCV形狀檢測的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45