1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        使用 OpenCV 測量物體尺寸

        共 16659字,需瀏覽 34分鐘

         ·

        2024-04-21 10:05

        點(diǎn)擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

            
        重磅干貨,第一時(shí)間送達(dá)
        你是否曾經(jīng)遇到過這樣的問題:想要知道計(jì)算器的精確尺寸,但手頭又沒有專業(yè)的測量工具?別擔(dān)心,今天我們就來教大家一個(gè)簡單又實(shí)用的方法,通過一張A4紙就能估算出計(jì)算器的寬度和高度,精確到毫米哦!
        該算法的主要思想其實(shí)非常簡單。請看下面圖 1 中我們要處理的樣本圖像。
        圖 1.本教程中使用的示例圖像。

        本教程的目的是估算計(jì)算器的寬度和高度(以毫米為單位)。為此,我們需要一個(gè)已知尺寸的物體作為參考長度。這基本上就是我們使用白紙作為對象背景的原因。紙張尺寸為 A4,這意味著它的寬度和高度分別為 210 毫米和 297 毫米。然后,我們可以借助這些數(shù)字獲得估計(jì)的計(jì)算器尺寸。
        在開始之前,我們這篇文章分為幾個(gè)章節(jié):
        1. 導(dǎo)入模塊和參數(shù)初始化
        2. 圖像加載和預(yù)處理
        3. 尋找紙張輪廓
        4. 透視變換
        5. 尋找物體輪廓
        6. 邊長計(jì)算
        7. 將所有內(nèi)容放在一個(gè)函數(shù)中
        現(xiàn)在,我們從第一個(gè)開始。

        1. 導(dǎo)入模塊及參數(shù)初始化

        和其他 Python 項(xiàng)目一樣,我要做的第一件事就是導(dǎo)入所有必需的模塊。在本例中,我們的大部分工作將使用 和 來完成cv2,numpymatplotlib僅用于顯示圖像。
            
        # Codeblock 1import cv2import numpy as npimport matplotlib.pyplot as plt


        由于模塊已導(dǎo)入,我們將初始化一些參數(shù),這些參數(shù)是未來計(jì)算所需的,您可以在下面的 Codeblock 2 中看到。變量SCALE主要用于我們不希望生成的圖像太小。同時(shí),和PAPER_W表示PAPER_H紙張寬度和高度(以毫米為單位)。
            
        # Codeblock 2SCALE = 3PAPER_W = 210 * SCALEPAPER_H = 297 * SCALE


        就這樣。第一章到此結(jié)束,因?yàn)檫@部分沒有什么可說的了。


        2.圖像加載和預(yù)處理

        之后,我們將創(chuàng)建一個(gè)名為和的函數(shù)load_image(),show_image()我認(rèn)為這兩個(gè)函數(shù)的名稱是不言自明的。它們的詳細(xì)信息可以在 Codeblock 3 中看到。您可以在下面看到我定義了參數(shù)scale(小寫),其中我的目的是使輸入圖像變得有點(diǎn)小,因?yàn)樵紙D像分辨率非常高。但是,從技術(shù)上講,您也可以通過傳遞大于 1 的值來使其更大。
        show_image()另一方面,該函數(shù)實(shí)現(xiàn)cv2.cvtColor() 了將顏色通道從 BGR 轉(zhuǎn)換為 RGB 的功能。這種轉(zhuǎn)換是必要的,因?yàn)?Matplotlib 在顏色通道順序方面與 OpenCV 的工作方式不同。
            
        # Codeblock 3def load_image(path, scale=0.7): img = cv2.imread(path) img_resized = cv2.resize(img, (0,0), None, scale, scale)return img_resized
        def show_image(img): img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) plt.figure(figsize=(6,8)) plt.xticks([]) plt.yticks([]) plt.imshow(img) plt.show()


        由于上面的兩個(gè)函數(shù)已經(jīng)初始化,現(xiàn)在我們可以使用它來實(shí)際加載圖像。這里我決定將參數(shù)保留scale為其默認(rèn)值(0.7),這將導(dǎo)致加載的圖像大小為 1120×840 px(原始大小為 1600×1200 px)。
            
        # Codeblock 4img_original = load_image(path='images/1.jpeg')show_image(img_original)print(img_original.shape)

        圖 2. 要處理的圖像尺寸為 1120 x 840 像素。

        我上面顯示的圖像存儲(chǔ)在 中img_original。接下來要做的步驟是使用一系列圖像處理技術(shù)對該圖像進(jìn)行預(yù)處理,即灰度轉(zhuǎn)換(#1)、模糊(#2)、Canny 邊緣檢測(#3)、擴(kuò)張(#5)和閉合(#6)。所有這些步驟都包含在preprocess_image()Codeblock 5 中的函數(shù)中。
            
        # Codeblock 5def preprocess_image(img, thresh_1=57, thresh_2=232): img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #1 img_blur = cv2.GaussianBlur(img_gray, (5,5), 1) #2 img_canny = cv2.Canny(img_blur, thresh_1, thresh_2) #3
        kernel = np.ones((3,3)) #4 img_dilated = cv2.dilate(img_canny, kernel, iterations=1) #5 img_closed = cv2.morphologyEx(img_dilated, cv2.MORPH_CLOSE, kernel, iterations=4) #6
        img_preprocessed = img_closed.copy()
        img_each_step = {'img_dilated': img_dilated, 'img_canny' : img_canny, 'img_blur' : img_blur, 'img_gray' : img_gray}
        return img_preprocessed, img_each_step
        在標(biāo)記為 的行中,和#2的參數(shù)分別表示高斯濾波器大小和高斯分布標(biāo)準(zhǔn)差。同時(shí),行中的和是 Canny 邊緣檢測器用來捕獲弱邊緣和強(qiáng)邊緣的兩個(gè)閾值。在本例中,我決定將 設(shè)置為 57 和232,這些數(shù)字是通過反復(fù)試驗(yàn)確定的。接下來,我們初始化一個(gè) 3×3 內(nèi)核,其中內(nèi)核的所有元素都設(shè)置為 1(標(biāo)記為 的行)。然后,這個(gè)全 1 內(nèi)核將在擴(kuò)張和閉合過程中用作結(jié)構(gòu)元素。(5,5)1thresh_1thresh_2#3thresh_1thresh_2#4

        preprocess_image()函數(shù)返回兩個(gè)值:完全預(yù)處理的圖像(存儲(chǔ)在 中img_preprocessed)和每個(gè)預(yù)處理階段的結(jié)果(img_each_step以字典形式存儲(chǔ)在 中)。該函數(shù)的輸出如圖 3 所示。要進(jìn)入下一個(gè)過程的圖像是img_preprocessed(最右邊)。
        # Codeblock 6img_preprocessed, img_each_step = preprocess_image(img_original)show_image(img_each_step['img_gray'])show_image(img_each_step['img_blur'])show_image(img_each_step['img_canny'])show_image(img_each_step['img_dilated'])show_image(img_preprocessed)

        圖 3. 從左到右的圖像轉(zhuǎn)換序列:灰度、模糊、邊緣檢測、擴(kuò)張和閉合。
        3. 尋找紙張輪廓
        獲取預(yù)處理后的圖像后,接下來要做的是使用 Codeblock 7 中顯示的代碼查找輪廓。您可以在那里看到我們使用cv2.findContours()( ) 來執(zhí)行此操作#1。我們還將其cv2.RETR_EXTERNAL作為參數(shù)的輸入?yún)?shù)傳遞,因?yàn)槲覀冎粚Σ东@圖像中檢測到的最外層輪廓(即紙張)感興趣?,F(xiàn)在,計(jì)算器對象將被忽略。然后,將使用( )mode繪制檢測到的輪廓本身。cv2.drawContours()#2
        # Codeblock 7def find_contours(img_preprocessed, img_original, epsilon_param=0.04):contours, hierarchy = cv2.findContours(image=img_preprocessed, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE)  #1img_contour = img_original.copy()cv2.drawContours(img_contour, contours, -1, (203,192,255), 6)  #2polygons = []for contour in contours:epsilon = epsilon_param * cv2.arcLength(curve=contour, closed=True)  #3polygon = cv2.approxPolyDP(curve=contour, epsilon=epsilon, closed=True)  #4polygon = polygon.reshape(4, 2)  #5polygons.append(polygon)for point in polygon:    img_contour = cv2.circle(img=img_contour, center=point, radius=8, color=(0,240,0), thickness=-1)  #6return polygons, img_contour不僅如此,這里我還嘗試使用cv2.approxPolyDP()(#4)來近似輪廓形狀。這行代碼的目的是獲取紙張輪廓的四個(gè)角,然后將坐標(biāo)存儲(chǔ)在其中polygon。我們需要注意的一件事是epsilon行中使用的參數(shù)#3。較小的 epsilon 值往往會(huì)導(dǎo)致檢測到更多的角,而另一方面,較大的 epsilon 會(huì)導(dǎo)致函數(shù)cv2.approxPolyDP()捕獲多邊形的一般形狀,即較少的角。注意 epsilon 值很重要,因?yàn)槲覀冃枰_保函數(shù)將準(zhǔn)確捕獲四個(gè)角點(diǎn)。
        需要執(zhí)行數(shù)組重塑 ( #5),因?yàn)?的原始輸出cv2.approxPolyDP()格式為(number of corners, 1, 2),其中中間軸在我們的例子中無關(guān)緊要。因此,我們可以放心地將其丟棄。除了函數(shù)之外find_contours(),我們還將使用cv2.circle()#6) 顯示角。然后,此函數(shù)將返回角坐標(biāo)本身 ( polygon) 和具有突出顯示輪廓的圖像 ( img_contour)。
        下面的代碼塊 8 顯示了我如何調(diào)用該find_contours()函數(shù)。在這里我決定將設(shè)置epsilon_param為 0.04。如果您使用自己的圖片,則可能需要更改此值,特別是如果光照特性與我的圖像不同。下面代碼塊的輸出(顯示在圖 4 中)顯示了輪廓和角落的樣子。我也打印了存儲(chǔ)在中的坐標(biāo)polygon[0]。如果您想知道,使用索引器 0 是因?yàn)樵?/span>find_contours()函數(shù)本質(zhì)上能夠捕獲多個(gè)輪廓,而在這種情況下,我們唯一的外部輪廓是紙張本身。除此之外,可能值得注意的是,存儲(chǔ)在中的坐標(biāo)polygons(x,y)格式,而不是(y,x)。
        # Codeblock 8polygons, img_contours = find_contours(img_preprocessed, img_original,epsilon_param=0.04)show_image(img_contours)polygons[0]

        圖 4. 輪廓(粉色)和角落(綠色)的樣子。
        4.透視變換
        由于已經(jīng)檢測到紙張角坐標(biāo),現(xiàn)在我們要根據(jù)這四個(gè)點(diǎn)來扭曲圖像。這個(gè)過程的目的是在我們開始尋找物體輪廓之前將紙張拉直。

        重新排序坐標(biāo)

        說到拉直過程,我們需要知道的一件事是,由于函數(shù)的性質(zhì),檢測到的多邊形角可能沒有排序cv2.approxPolyDP()。為了使這四個(gè)點(diǎn)都有序,我們需要?jiǎng)?chuàng)建一個(gè)專門的函數(shù)來執(zhí)行此操作。我正在談?wù)摰暮瘮?shù)稱為,reorder_coords()其詳細(xì)信息可在 Codeblock 9 中看到。
            
        # Codeblock 9def reorder_coords(polygon): rect_coords = np.zeros((4, 2))
        add = polygon.sum(axis=1) rect_coords[0] = polygon[np.argmin(add)] # Top left rect_coords[3] = polygon[np.argmax(add)] # Bottom right
        subtract = np.diff(polygon, axis=1) rect_coords[1] = polygon[np.argmin(subtract)] # Top right rect_coords[2] = polygon[np.argmax(subtract)] # Bottom left
        return rect_coords


        上述函數(shù)的工作原理是將兩個(gè)坐標(biāo)數(shù)字相加和相減,得到 argmin 和 argmax。這些代碼行神奇地將左上角、右上角、左下角和右下角分別放在索引 0、1、2 和 3 處。然后,我們可以將此函數(shù)應(yīng)用于存儲(chǔ)在中的點(diǎn),polygon[0]如 Codeblock 10 所示。
            
        # Codeblock 10rect_coords = np.float32(reorder_coords(polygons[0]))rect_coords

        圖 5. 我們使用reorder_coords()函數(shù)排序的紙張的四個(gè)角點(diǎn)。

        稍后,上方重新排序的紙張角坐標(biāo)(rect_coords)將作為變換的源,而變換目標(biāo)(paper_coords)由實(shí)際紙張大小決定,即PAPER_WPAPER_H。查看 Codeblock 11 以了解我如何手動(dòng)排列 存儲(chǔ)的點(diǎn)。這里要記住的一件事是,目標(biāo)坐標(biāo)的順序需要與源坐標(biāo)的順序完全匹配,這就是我們實(shí)現(xiàn)重新排序源坐標(biāo)的功能paper_coords的原因。reorder_coords()
            
        # Codeblock 11paper_coords = np.float32([[0,0], # Top left [PAPER_W,0], # Top right [0,PAPER_H], # Bottom left [PAPER_W,PAPER_H]]) # Bottom rightpaper_coords

        圖 6.用于圖像轉(zhuǎn)換的目標(biāo)坐標(biāo)。

        除了代碼塊 10 和 11 之外,您可能還注意到我將數(shù)組數(shù)據(jù)類型轉(zhuǎn)換為 float32。事實(shí)上,我嘗試使用其他數(shù)據(jù)類型,例如 int32 和 float64,結(jié)果發(fā)現(xiàn)這兩種數(shù)據(jù)類型都導(dǎo)致cv2.getPerspectiveTransform()后續(xù)代碼塊中的函數(shù)返回錯(cuò)誤。

        創(chuàng)建變換矩陣

        此時(shí),我們已經(jīng)得到了rect_coordspaper_coords。我們現(xiàn)在可以使用它們來扭曲原始圖像,使用cv2.getPerspectiveTransform()和,cv2.warpPerspective()如下面的代碼塊 12 所示。為了讓代碼更簡潔,我將它們放在另一個(gè)名為的函數(shù)中warp_image()。
            
        # Codeblock 12def warp_image(rect_coords, paper_coords, img_original, pad=5):
        matrix = cv2.getPerspectiveTransform(src=rect_coords, dst=paper_coords) #1img_warped = cv2.warpPerspective(img_original, matrix,(PAPER_W, PAPER_H)) #2
        warped_h = img_warped.shape[0]warped_w = img_warped.shape[1]img_warped = img_warped[pad:warped_h-pad, pad:warped_w-pad] #3
        return img_warped


        讓我們深入研究上述函數(shù)。我們首先使用cv2.getPerspectiveTransform()#1) 創(chuàng)建所謂的變換矩陣。變換矩陣本身的尺寸為 3 × 3,它存儲(chǔ)了有關(guān)如何將圖像從一個(gè)角度變換到另一個(gè)角度的信息。然后,該矩陣將實(shí)際用于使用cv2.warpPerspective()#2) 變換原始圖像。然后,我們將變換后的圖像存儲(chǔ)在名為 的變量中img_warped。除了函數(shù)之外warp_image(),我們還將丟棄圖像邊界附近的區(qū)域 ( #3),因?yàn)樯傻膱D像可能在邊緣處包含一個(gè)狹窄的不需要的黑色區(qū)域。
        函數(shù)的使用warp_image()在 Codeblock 13 中演示,其中輸出顯示在圖 7 中。
            
        # Codeblock 13img_warped = warp_image(rect_coords, paper_coords, img_original)show_image(img_warped)print(img_warped.shape)

        圖 7.扭曲的圖像。

        5. 查找物體輪廓
        由于原始圖像已根據(jù)紙張形狀進(jìn)行了扭曲,接下來我將執(zhí)行完全相同的過程以檢測計(jì)算器對象,即圖像預(yù)處理和輪廓搜索。由于要執(zhí)行的過程與之前的過程相同,因此我們可以簡單地重用我們之前定義的函數(shù)。在這種情況下,我們的內(nèi)部輪廓(即計(jì)算器按鈕)將被忽略,這要?dú)w功于cv2.RETR_EXTERNAL我們在 Codeblock 7 中實(shí)現(xiàn)的輪廓。
        現(xiàn)在,Codeblock 14 和 15 展示了如何進(jìn)行預(yù)處理和輪廓查找。
            
        # Codeblock 14img_warped_preprocessed, _ = preprocess_image(img_warped)show_image(img_warped_preprocessed)

        圖 8.已預(yù)處理的扭曲圖像。
            
        # Codeblock 15polygons_warped, img_contours_warped = find_contours(img_warped_preprocessed, img_warped,epsilon_param=0.04)show_image(img_contours_warped)polygons_warped[0]

        圖 9. 檢測到的輪廓(粉色)和角落(綠色)。

        由于上面兩個(gè)Codeblocks中的代碼都已經(jīng)運(yùn)行完畢,現(xiàn)在所有角點(diǎn)坐標(biāo)(綠色圓圈)都存儲(chǔ)在 中polygons_warped,這四個(gè)坐標(biāo)值其實(shí)就是用來估算邊長的坐標(biāo)值。

        6. 邊長計(jì)算

        在這種情況下,我們假設(shè)紙張上方的所有物體都是矩形。因此,可以通過計(jì)算物體左上角和左下角之間的歐幾里得距離來估計(jì)物體的高度(Codeblock 16 #2)。同時(shí),可以通過計(jì)算物體左上角和右上角之間的相同距離度量來獲得寬度(#3)。此外,我們需要記住,返回的檢測到的角find_contours()仍然是無序的。因此,我們需要reorder_coords()事先調(diào)用( )。我想在 Codeblock 16 中強(qiáng)調(diào)的最后一件事是,估計(jì)的高度和寬度現(xiàn)在存儲(chǔ)在按相應(yīng)順序#1命名的數(shù)組中( )sizes#4
            
        # Codeblock 16def calculate_sizes(polygons_warped):
        rect_coords_list = []for polygon in polygons_warped:rect_coords = np.float32(reorder_coords(polygon)) #1rect_coords_list.append(rect_coords)
        heights = []widths = []for rect_coords in rect_coords_list:height = cv2.norm(rect_coords[0], rect_coords[2], cv2.NORM_L2) #2width = cv2.norm(rect_coords[0], rect_coords[1], cv2.NORM_L2) #3
        heights.append(height)widths.append(width)
        heights = np.array(heights).reshape(-1,1)widths = np.array(widths).reshape(-1,1)
        sizes = np.hstack((heights, widths)) #4
        return sizes, rect_coords_list
        sizes, rect_coords_list = calculate_sizes(polygons_warped)sizes
        圖 10. 計(jì)算器的高度(索引 0)和寬度(索引 1)(以像素為單位)。

        轉(zhuǎn)換為毫米

        但是,我們需要記住,圖 10 中的輸出仍然是像素?cái)?shù)。要將這些值轉(zhuǎn)換為毫米,我們需要為此創(chuàng)建一個(gè)單獨(dú)的函數(shù),我將其命名為convert_to_mm()(Codeblock 17)。此函數(shù)通過取紙張長度(以毫米為單位)和像素(以像素為單位)的比率來工作。然后,我們可以通過將比率值(和)與仍以像素為單位的計(jì)算器大?。ê?/span>#1#2相乘來獲得實(shí)際的毫米長度。scale_hscale_w#3#4
            
        # Codeblock 17def convert_to_mm(sizes_pixel, img_warped):warped_h = img_warped.shape[0]warped_w = img_warped.shape[1]
        scale_h = PAPER_H / warped_h #1scale_w = PAPER_W / warped_w #2
        sizes_mm = []
        for size_pixel_h, size_pixel_w in sizes_pixel:size_mm_h = size_pixel_h * scale_h / SCALE #3size_mm_w = size_pixel_w * scale_w / SCALE #4
        sizes_mm.append([size_mm_h, size_mm_w])
        return np.array(sizes_mm)
        sizes_mm = convert_to_mm(sizes, img_warped)sizes_mm
        圖 11. 已轉(zhuǎn)換為毫米的計(jì)算器高度和寬度。

        到目前為止,我們已經(jīng)成功獲得了邊緣的長度(以毫米為單位)?,F(xiàn)在,我們將以文本的形式顯示這些值,這些文本寫在扭曲的圖像上。為此完成的整個(gè)過程都放在函數(shù)內(nèi)部write_size()。初始化函數(shù)后,我們可以直接調(diào)用它,如#1代碼塊 18 中所示。此代碼的輸出如圖 12 所示。
        看起來我們的代碼如預(yù)期那樣工作了。
            
        # Codeblock 18def write_size(rect_coords_list, sizes, img_warped):
        img_result = img_warped.copy()
        for rect_coord, size in zip(rect_coords_list, sizes):
        top_left = rect_coord[0].astype(int) top_right = rect_coord[1].astype(int) bottom_left = rect_coord[2].astype(int)
        cv2.line(img_result, top_left, top_right, (255,100,50), 4) cv2.line(img_result, top_left, bottom_left, (100,50,255), 4)
        cv2.putText(img_result, f'{np.int32(size[0])} mm', (bottom_left[0]-20, bottom_left[1]+50), cv2.FONT_HERSHEY_DUPLEX, 1, (100,50,255), 1)
        cv2.putText(img_result, f'{np.int32(size[1])} mm', (top_right[0]+20, top_right[1]+20), cv2.FONT_HERSHEY_DUPLEX, 1, (255,100,50), 1)
        return img_result
        img_result = write_size(rect_coords_list, sizes_mm, img_warped) #1show_image(img_result)print(img_result.shape)


        圖 12. 在圖像上添加文字。

        7. 將所有內(nèi)容放在一個(gè)函數(shù)中

        由于我試圖解釋此項(xiàng)目中代碼使用的每個(gè)部分,因此我們上述執(zhí)行的所有步驟似乎很長。事實(shí)上,到目前為止您看到的所有代碼都可以包裝在一個(gè)函數(shù)中,我measure_size()在 Codeblock 19 中將其命名為該函數(shù)。使用此函數(shù),我們可以簡單地將要處理的圖像與參數(shù)一起傳遞,以完成我們剛剛完成的所有工作。
            
        # Codeblock 19def measure_size(path, img_original_scale=0.7,PAPER_W=210, PAPER_H=297, SCALE=3, paper_eps_param=0.04, objects_eps_param=0.05, canny_thresh_1=57, canny_thresh_2=232):
        PAPER_W = PAPER_W * SCALEPAPER_H = PAPER_H * SCALE
        # Loading and preprocessing original image.img_original = load_image(path=path, scale=img_original_scale)img_preprocessed, img_each_step = preprocess_image(img_original, thresh_1=canny_thresh_1, thresh_2=canny_thresh_2)
        # Finding paper contours and corners.polygons, img_contours = find_contours(img_preprocessed, img_original, epsilon_param=paper_eps_param)
        # Reordering paper corners.rect_coords = np.float32(reorder_coords(polygons[0]))
        # Warping image according to paper contours.paper_coords = np.float32([[0,0], [PAPER_W,0], [0,PAPER_H],[PAPER_W,PAPER_H]])img_warped = warp_image(rect_coords, paper_coords, img_original)
        # Preprocessing the warped image.img_warped_preprocessed, _ = preprocess_image(img_warped)
        # Finding contour in the warped image.polygons_warped, img_contours_warped = find_contours(img_warped_preprocessed, img_warped,epsilon_param=objects_eps_param)
        # Edge langth calculation.sizes, rect_coords_list = calculate_sizes(polygons_warped)sizes_mm = convert_to_mm(sizes, img_warped)img_result = write_size(rect_coords_list, sizes_mm, img_warped)
        return img_result


        一旦measure_size()創(chuàng)建了函數(shù),我們現(xiàn)在就可以在幾個(gè)測試用例上測試它。圖 13 所示的輸出表明,我們估算物體大小的方法對于不同的矩形物體非常有效。
            
        # Codeblock 20show_image(measure_size('images/1.jpeg'))show_image(measure_size('images/2.jpeg'))show_image(measure_size('images/3.jpeg'))show_image(measure_size('images/4.jpeg'))show_image(measure_size('images/5.jpeg'))show_image(measure_size('images/6.jpeg', objects_eps_param=0.1))


        圖 13.其他圖像上的結(jié)果。

        一些局限

        盡管在許多情況下我們的方法都運(yùn)行正常,但這并不一定意味著我們的工作是完美的,即使在受控環(huán)境中也是如此。如果你仔細(xì)觀察,你可能會(huì)注意到大多數(shù)預(yù)測的角點(diǎn)實(shí)際上并不位于實(shí)際的角點(diǎn)位置,這可能會(huì)導(dǎo)致測量結(jié)果有點(diǎn)不準(zhǔn)確。這主要是因?yàn)榻屈c(diǎn)的確定高度依賴于二值圖像(即閉運(yùn)算后的圖像)的質(zhì)量。這意味著在這種情況下輸入?yún)?shù)值的確定非常關(guān)鍵。
        此外,如果我們查看圖 13 中從右側(cè)開始的第二張圖像,您會(huì)發(fā)現(xiàn)對象尺寸沒有打印出來。這可能是因?yàn)橛捎趯ο蠛图垙堉g的細(xì)微顏色差異,輪廓檢測不太好。此外,在我們的最后一張測試圖像(最右邊的一張)中,盡管對象的整體外觀呈矩形,但我們的實(shí)現(xiàn)似乎難以準(zhǔn)確測量具有弧形角的對象的尺寸。
           
        下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
        在「小白學(xué)視覺」公眾號后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

        下載2:Python視覺實(shí)戰(zhàn)項(xiàng)目52講
        小白學(xué)視覺公眾號后臺(tái)回復(fù):Python視覺實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計(jì)數(shù)、添加眼線、車牌識(shí)別、字符識(shí)別、情緒檢測、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺。

        下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講
        小白學(xué)視覺公眾號后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

        交流群


        歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會(huì)逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會(huì)根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會(huì)請出群,謝謝理解~


        瀏覽 184
        10點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        10點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            暴露超短裙乳蒂环捆绑调教 | 豆花视频91 | 无毛嫩逼一级片网 | 国产激情视频在线观看 | 蜜桃视频在线观看www | 免费看成人A片无码照片 | 国产在线播精品第三 | 国产一级在线看 | 欧美日韩精品A∨一区二区三区电影 | 国产精品诱惑 |