丁香五月天婷婷久久婷婷色综合91|国产传媒自偷自拍|久久影院亚洲精品|国产欧美VA天堂国产美女自慰视屏|免费黄色av网站|婷婷丁香五月激情四射|日韩AV一区二区中文字幕在线观看|亚洲欧美日本性爱|日日噜噜噜夜夜噜噜噜|中文Av日韩一区二区

您正在使用IE低版瀏覽器,為了您的雷峰網(wǎng)賬號安全和更好的產(chǎn)品體驗,強烈建議使用更快更安全的瀏覽器
此為臨時鏈接,僅用于文章預(yù)覽,將在時失效
人工智能開發(fā)者 正文
發(fā)私信給AI研習(xí)社-譯站
發(fā)送

0

用 OpenCV 檢測圖像中各物體大小

本文作者: AI研習(xí)社-譯站 2018-06-25 15:06
導(dǎo)語:我們需要定義一個比值,用于測量每個給定指標(biāo)的像素個數(shù),我將其稱為「像素/度量」比率。

雷鋒網(wǎng) AI 研習(xí)社按:本文為雷鋒網(wǎng)字幕組編譯的技術(shù)博客,原標(biāo)題為 Measuring size of objects in an image with OpenCV,作者為 Adrian Rosebrock 。

翻譯 | 塵央    整理 |  孔令雙

原文鏈接:

https://www.pyimagesearch.com/2016/03/28/measuring-size-of-objects-in-an-image-with-opencv/

用 OpenCV 檢測圖像中各物體大小

在圖像中測量物體的大小與計算從相機到物體之間的距離是相似的,在這兩種情況下,我們需要定義一個比值,它測量每個給定指標(biāo)的像素個數(shù)。  

我將其稱為「像素/度量」比率,在下一節(jié)中我將更正式地定義它。  

「像素/度量」比率

為了確定圖像中物體的大小,我們首先需要使用一個 參考物體進行「校準(zhǔn)」(不要與內(nèi)部/外部校準(zhǔn)混淆)。我們的參考物體應(yīng)該有兩個重要的屬性:  

  • 屬性 1:我們應(yīng)該在一個可測量的單位(如毫米、英寸等)內(nèi),知道這個物體的尺寸(根據(jù)寬度或高度)。

  • 屬性 2:我們應(yīng)該能夠在圖像中輕松地找到這個參考物體,要么基于物體的位置(如參考物體總是被放置在圖像的左上角)或通過表象(像一個獨特的顏色或形狀,獨特且不同于其他物體的物體)。在任何一種情況下,我們的參考都應(yīng)該以某種方式具有惟一的可識別性。

在本例中,我們將使用一個兩角五分的美元硬幣作為參考物體,并在所有示例中確保它始終是圖像中最左的物體: 

用 OpenCV 檢測圖像中各物體大小

圖1:我們將使用一個兩角五分的美元硬幣作為參照物,并確保它始終作為圖像中最左邊的物體放置,這樣我們就可以很容易地根據(jù)輪廓的位置對其進行排序。  

通過保證1 / 4是最左的物體,我們可以從左到右對物體輪廓進行排序,獲取1 / 4(這將始終是排序列表中的第一個輪廓),并使用它來定義我們的 pixels_per_metric ,我們將其定義為:  

pixels_per_metric = object_width / know_width

一個兩角五分的美元硬幣是 0.955 英寸?,F(xiàn)在假設(shè)我們的 object_width  (以像素為單位)被計算為 150 像素寬(基于它的相關(guān)邊框)。

因此,pixels_per_metric 為:

pixels_per_metric = 150px / 0.955in = 157px

因此,在我們的圖像中,每 0.955 英寸大約有 157 個像素。利用這個比率,我們可以計算圖像中物體的大小。  

基于計算機視覺的物體尺寸檢測

既然我們知道「像素/度量」比率  ,就可以實現(xiàn)用于測量圖像中物體大小的 Python 驅(qū)動程序腳本。

新建一個文件,將其命名為 object_size.py ,插入以下代碼:

# import the necessary packages

from scipy.spatial import distance as dist

from imutils import perspective

from imutils import contours

import numpy as np

import argparse

import imutils

import cv2

 

def midpoint(ptA, ptB):

return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)

 

# construct the argument parse and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument("-i", "--image", required=True,

help="path to the input image")

ap.add_argument("-w", "--width", type=float, required=True,

help="width of the left-most object in the image (in inches)")

args = vars(ap.parse_args())

第 2 行到第 8 行導(dǎo)入我們需要的 Python 包。在該例中,我們將充分利用  imutils package  ,所以如果你沒有安裝這個包,確保在繼續(xù)下一步之前安裝這個包。

$ pip install imutils

否則,如果你確實安裝了 imutils ,請確保你有最新的版本,本文的版本為 0.3.6:  

pip install --upgrade imutils

第 10 行和第 11 行定義一個稱為中點的輔助方法,顧名思義,用于計算(x, y)-坐標(biāo)的兩組之間的中點。

第 14 行到第 19 解析我們的命令行參數(shù)。我們需要兩個參數(shù):一個是圖像,該圖像為包含我們想測量物體的輸入圖像的路徑,第二個是參照物的寬度(以英寸為單位),假定參照物在我們圖像中的最左端。

現(xiàn)在,我們能加載我們的圖像并對其進行預(yù)處理:

# load the image, convert it to grayscale, and blur it slightly

image = cv2.imread(args["image"])

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

gray = cv2.GaussianBlur(gray, (7, 7), 0)

 

# perform edge detection, then perform a dilation + erosion to

# close gaps in between object edges

edged = cv2.Canny(gray, 50, 100)

edged = cv2.dilate(edged, None, iterations=1)

edged = cv2.erode(edged, None, iterations=1)

 

# find contours in the edge map

cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,

cv2.CHAIN_APPROX_SIMPLE)

cnts = cnts[0] if imutils.is_cv2() else cnts[1]

 

# sort the contours from left-to-right and initialize the

# 'pixels per metric' calibration variable

(cnts, _) = contours.sort_contours(cnts)

pixelsPerMetric = None

第 2 行到第 4 行:從磁盤中加載我們的圖像,將該圖像灰度化,并利用高斯過濾器將其平滑化。第 8 行到第 10 行:對其進行邊緣檢測,并通過膨脹和腐蝕使邊緣過渡得更加平滑。

第 13 行到第 15 行:在邊緣檢測后的圖中尋找與物體一致的邊緣(例如輪廓)。

第 19 行:將這些邊緣從左到右排序(允許我們提取參照物)。第 20 行:初始化 pixelsPerMetric 值。

下一步就是檢測每個輪廓:

# loop over the contours individually

for c in cnts:

# if the contour is not sufficiently large, ignore it

if cv2.contourArea(c) < 100:

continue

 

# compute the rotated bounding box of the contour

orig = image.copy()

box = cv2.minAreaRect(c)

box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)

box = np.array(box, dtype="int")

 

# order the points in the contour such that they appear

# in top-left, top-right, bottom-right, and bottom-left

# order, then draw the outline of the rotated bounding

# box

box = perspective.order_points(box)

cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)

 

# loop over the original points and draw them

for (x, y) in box:

cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)

在第 2 行,我們開始對每個輪廓進行循環(huán)。如果輪廓不夠大,我們丟棄該區(qū)域,假設(shè)它是邊緣檢測過程中遺留下來的噪聲(第 4 行和第 5 行)。

倘若輪廓區(qū)域足夠大,我們在第 9-11 行計算圖像的旋轉(zhuǎn)邊界框,特別注意使用 OpenCV 2.4 的 cv2.cv.BoxPoints 函數(shù)和 OpenCV 3 的 cv2.boxPoints 方法。

在第 17 行,我們在左上方、右上角、右下角和左下方的順序排列我們旋轉(zhuǎn)的邊界框坐標(biāo),如上周的博客文章所說的那樣。

最后,第 18-21 行以綠色繪制物體的輪廓,然后將邊界框矩形的頂點繪制成紅色的小圓圈。

既然我們已經(jīng)將邊界矩形框排好序了,就能計算出一系列的中點:

# unpack the ordered bounding box, then compute the midpoint

# between the top-left and top-right coordinates, followed by

# the midpoint between bottom-left and bottom-right coordinates

(tl, tr, br, bl) = box

(tltrX, tltrY) = midpoint(tl, tr)

(blbrX, blbrY) = midpoint(bl, br)

 

# compute the midpoint between the top-left and top-right points,

# followed by the midpoint between the top-righ and bottom-right

(tlblX, tlblY) = midpoint(tl, bl)

(trbrX, trbrY) = midpoint(tr, br)

 

# draw the midpoints on the image

cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)

cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)

cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)

cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)

 

# draw lines between the midpoints

cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),

(255, 0, 255), 2)

cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),

(255, 0, 255), 2)

第 4-6 行打開我們的有序邊界框,計算左上角和右上角之間的中點,然后計算右下角之間的中點。

我們還將分別計算左上+左下+右上+右下+右下之間的中點(第 10 行和第 11 行)。

第 14-17 行在圖像上繪制藍(lán)色中間點,然后將中間點與紫色線連接。

接下來,我們需要通過調(diào)查參照物來初始化 pixelsPerMetric 變量:

# compute the Euclidean distance between the midpoints

dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))

dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

 

# if the pixels per metric has not been initialized, then

# compute it as the ratio of pixels to supplied metric

# (in this case, inches)

if pixelsPerMetric is None:

pixelsPerMetric = dB / args["width"]

首先,我們計算出我們的中點集合之間的歐氏距離(第 2 和 3 行)。dA 變量將包含高度距離(以像素為單位),而 dB 將保留寬度距離。

然后在第 8 行進行檢查,看看我們的 pixelsPerMetric 變量是否被初始化了,如果沒有初始化,我們將 dB 除以我們提供的寬度,從而得到(近似的)像素/英寸。

既然我們的 pixelsPerMetric 變量已經(jīng)被定義,我們就可以測量圖像中物體的大小:

# compute the size of the object

dimA = dA / pixelsPerMetric

dimB = dB / pixelsPerMetric

 

# draw the object sizes on the image

cv2.putText(orig, "{:.1f}in".format(dimA),

(int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,

0.65, (255, 255, 255), 2)

cv2.putText(orig, "{:.1f}in".format(dimB),

(int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,

0.65, (255, 255, 255), 2)

 

# show the output image

cv2.imshow("Image", orig)

cv2.waitKey(0)

第 2 行和 3 行通過將各自的歐幾里得距離除以像素值來計算物體的尺寸(以英寸為單位)。

第 6-11 行繪制圖像上物體的尺寸,第 14 行和第 15 行顯示輸出結(jié)果。

檢測物體大小的結(jié)果

為了測試我們  object_size.py  腳本,只需用以下命令:

$ python object_size.py --image images/example_01.png --width 0.955

你的輸出結(jié)果應(yīng)該如下所示:

用 OpenCV 檢測圖像中各物體大小

圖 2:使用 OpenCV 、Python 、計算機視覺和圖像處理技術(shù)測量圖像中物體的大小。

上圖所示,我們已經(jīng)成功地計算出圖像中每個物體的大小——我們的名片被正確地顯示為 3.5 英寸 x 2英寸。同樣,我們的鎳被準(zhǔn)確地描述為 0.8 英寸 x 0.8 英寸。

盡管如此,并不是所有的結(jié)果都很精確。

Gameboy 墨盒的尺寸略有不同(盡管大小相同)。兩個季度的高度也下降了 0.1 英寸。  

所以,這是為什么呢?怎么物體的檢測不是百分百的準(zhǔn)確呢?原因是雙重的:

  1. 首先,我趕緊用我的 iPhone 拍了這張照片。這個角度當(dāng)然不是完全 90 度地「向下看」物體(就像鳥瞰一樣)。如果不是完全 90 度視圖(或者盡可能接近它),物體的尺寸可能會顯得扭曲。

  2. 其次,我沒有使用相機的內(nèi)部和外部參數(shù)來校準(zhǔn)我的 iPhone 。如果不確定這些參數(shù),照片很容易出現(xiàn)徑向和切向鏡頭畸變。為了找到這些參數(shù)而執(zhí)行額外的校準(zhǔn)步驟,可以「不扭曲」我們的圖像,并導(dǎo)致更好的對象大小近似(但我將把失真校正的討論作為未來博客文章的主題)。

與此同時,在拍攝物體時,盡量接近 90 度的視角 —— 這將有助于提高你對物體大小的估計的準(zhǔn)確性。

讓我們看第二個測量物體尺寸的例子,這次測量藥丸的尺寸:

$ python object_size.py --image images/example_02.png --width 0.955

用 OpenCV 檢測圖像中各物體大小

圖3:用 OpenCV 測量圖像中藥丸的尺寸

在美國,20000 多種處方藥中有近 50% 是圓形和/或白色的,因此如果我們能根據(jù)它們的測量結(jié)果對藥片進行過濾,我們就更有可能準(zhǔn)確地識別出藥物。  

最后,我們最后一個例子,這次使用 3.5 英寸 x2 英寸的名片來測量兩個唱片 EPs 和一個信封的大小: 

$ python object_size.py --image images/example_03.png --width 3.5

用 OpenCV 檢測圖像中各物體大小

圖4:最后一個用 Python + OpenCV 測量圖像中物體大小的例子。

同樣,結(jié)果也不是很完美,但這是由于(1)視角和(2)透鏡失真,如上所述。  

總結(jié)

在本篇博客中,我們學(xué)習(xí)了如何通過 Python 和 OpenCV 檢測圖像中的物體大小。

就像在我們的教程中,要測量從相機到物體的距離,需要確定「像素/度量」比率,它描述了能夠「適應(yīng)」特定數(shù)目的英寸、毫米、米等的像素的數(shù)量。

為了計算這個比率,我們需要一個具有兩個重要屬性的參照物:

  • 屬性 1:我們知道該參照物的尺寸(比如寬和高)以及其測量單位(英尺,毫米等)。

  • 屬性 2:該參照物應(yīng)該很容易找到,無論是在對象的位置上還是在外觀上。

如果可以滿足這兩個屬性,那么可以使用該參照物來校準(zhǔn) pixels_per_metric 變量,然后計算圖像中其他物體的大小。

在下一篇博文中,我們將進一步介紹這個例子,并學(xué)習(xí)如何計算圖像中各物體之間的距離。

一定要使用下面的表格注冊 PyImageSearch 的通訊,當(dāng)下一篇博客文章發(fā)布時,你將會收到通知——你不容錯過!

雷鋒網(wǎng)字幕組編譯。

用 OpenCV 檢測圖像中各物體大小

雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。

用 OpenCV 檢測圖像中各物體大小

分享:
相關(guān)文章

知情人士

AI研習(xí)社(yanxishe.com)譯站頻道,傳播前沿人工智能知識,讓語言不再成為學(xué)習(xí)知識的門檻。(原雷鋒字幕組)
當(dāng)月熱門文章
最新文章
請?zhí)顚懮暾埲速Y料
姓名
電話
郵箱
微信號
作品鏈接
個人簡介
為了您的賬戶安全,請驗證郵箱
您的郵箱還未驗證,完成可獲20積分喲!
請驗證您的郵箱
立即驗證
完善賬號信息
您的賬號已經(jīng)綁定,現(xiàn)在您可以設(shè)置密碼以方便用郵箱登錄
立即設(shè)置 以后再說