<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 OpenCV 測量物體尺寸

          共 16659字,需瀏覽 34分鐘

           ·

          2024-04-21 10:05

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

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

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

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

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


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


          就這樣。第一章到此結(jié)束,因為這部分沒有什么可說的了。


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

          之后,我們將創(chuàng)建一個名為和的函數(shù)load_image()show_image()我認(rèn)為這兩個函數(shù)的名稱是不言自明的。它們的詳細(xì)信息可以在 Codeblock 3 中看到。您可以在下面看到我定義了參數(shù)scale(小寫),其中我的目的是使輸入圖像變得有點小,因為原始圖像分辨率非常高。但是,從技術(shù)上講,您也可以通過傳遞大于 1 的值來使其更大。
          show_image()另一方面,該函數(shù)實現(xiàn)cv2.cvtColor() 了將顏色通道從 BGR 轉(zhuǎn)換為 RGB 的功能。這種轉(zhuǎ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()


          由于上面的兩個函數(shù)已經(jīng)初始化,現(xiàn)在我們可以使用它來實際加載圖像。這里我決定將參數(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 像素。

          我上面顯示的圖像存儲在 中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)差。同時,行中的和是 Canny 邊緣檢測器用來捕獲弱邊緣和強(qiáng)邊緣的兩個閾值。在本例中,我決定將 設(shè)置為 57 和232,這些數(shù)字是通過反復(fù)試驗確定的。接下來,我們初始化一個 3×3 內(nèi)核,其中內(nèi)核的所有元素都設(shè)置為 1(標(biāo)記為 的行)。然后,這個全 1 內(nèi)核將在擴(kuò)張和閉合過程中用作結(jié)構(gòu)元素。(5,5)1thresh_1thresh_2#3thresh_1thresh_2#4

          preprocess_image()函數(shù)返回兩個值:完全預(yù)處理的圖像(存儲在 中img_preprocessed)和每個預(yù)處理階段的結(jié)果(img_each_step以字典形式存儲在 中)。該函數(shù)的輸出如圖 3 所示。要進(jìn)入下一個過程的圖像是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ù)傳遞,因為我們只對捕獲圖像中檢測到的最外層輪廓(即紙張)感興趣。現(xiàn)在,計算器對象將被忽略。然后,將使用( )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)來近似輪廓形狀。這行代碼的目的是獲取紙張輪廓的四個角,然后將坐標(biāo)存儲在其中polygon。我們需要注意的一件事是epsilon行中使用的參數(shù)#3。較小的 epsilon 值往往會導(dǎo)致檢測到更多的角,而另一方面,較大的 epsilon 會導(dǎo)致函數(shù)cv2.approxPolyDP()捕獲多邊形的一般形狀,即較少的角。注意 epsilon 值很重要,因為我們需要確保函數(shù)將準(zhǔn)確捕獲四個角點。
          需要執(zhí)行數(shù)組重塑 ( #5),因為 的原始輸出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 中)顯示了輪廓和角落的樣子。我也打印了存儲在中的坐標(biāo)polygon[0]。如果您想知道,使用索引器 0 是因為該find_contours()函數(shù)本質(zhì)上能夠捕獲多個輪廓,而在這種情況下,我們唯一的外部輪廓是紙張本身。除此之外,可能值得注意的是,存儲在中的坐標(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ù)這四個點來扭曲圖像。這個過程的目的是在我們開始尋找物體輪廓之前將紙張拉直。

          重新排序坐標(biāo)

          說到拉直過程,我們需要知道的一件事是,由于函數(shù)的性質(zhì),檢測到的多邊形角可能沒有排序cv2.approxPolyDP()。為了使這四個點都有序,我們需要創(chuàng)建一個專門的函數(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ù)的工作原理是將兩個坐標(biāo)數(shù)字相加和相減,得到 argmin 和 argmax。這些代碼行神奇地將左上角、右上角、左下角和右下角分別放在索引 0、1、2 和 3 處。然后,我們可以將此函數(shù)應(yīng)用于存儲在中的點,polygon[0]如 Codeblock 10 所示。
              
          # Codeblock 10rect_coords = np.float32(reorder_coords(polygons[0]))rect_coords

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

          稍后,上方重新排序的紙張角坐標(biāo)(rect_coords)將作為變換的源,而變換目標(biāo)(paper_coords)由實際紙張大小決定,即PAPER_WPAPER_H。查看 Codeblock 11 以了解我如何手動排列 存儲的點。這里要記住的一件事是,目標(biāo)坐標(biāo)的順序需要與源坐標(biāo)的順序完全匹配,這就是我們實現(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ù)據(jù)類型,例如 int32 和 float64,結(jié)果發(fā)現(xiàn)這兩種數(shù)據(jù)類型都導(dǎo)致cv2.getPerspectiveTransform()后續(xù)代碼塊中的函數(shù)返回錯誤。

          創(chuàng)建變換矩陣

          此時,我們已經(jīng)得到了rect_coordspaper_coords。我們現(xiàn)在可以使用它們來扭曲原始圖像,使用cv2.getPerspectiveTransform()和,cv2.warpPerspective()如下面的代碼塊 12 所示。為了讓代碼更簡潔,我將它們放在另一個名為的函數(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,它存儲了有關(guān)如何將圖像從一個角度變換到另一個角度的信息。然后,該矩陣將實際用于使用cv2.warpPerspective()#2) 變換原始圖像。然后,我們將變換后的圖像存儲在名為 的變量中img_warped。除了函數(shù)之外warp_image(),我們還將丟棄圖像邊界附近的區(qū)域 ( #3),因為生成的圖像可能在邊緣處包含一個狹窄的不需要的黑色區(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í)行完全相同的過程以檢測計算器對象,即圖像預(yù)處理和輪廓搜索。由于要執(zhí)行的過程與之前的過程相同,因此我們可以簡單地重用我們之前定義的函數(shù)。在這種情況下,我們的內(nèi)部輪廓(即計算器按鈕)將被忽略,這要歸功于cv2.RETR_EXTERNAL我們在 Codeblock 7 中實現(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. 檢測到的輪廓(粉色)和角落(綠色)。

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

          6. 邊長計算

          在這種情況下,我們假設(shè)紙張上方的所有物體都是矩形。因此,可以通過計算物體左上角和左下角之間的歐幾里得距離來估計物體的高度(Codeblock 16 #2)。同時,可以通過計算物體左上角和右上角之間的相同距離度量來獲得寬度(#3)。此外,我們需要記住,返回的檢測到的角find_contours()仍然是無序的。因此,我們需要reorder_coords()事先調(diào)用( )。我想在 Codeblock 16 中強(qiáng)調(diào)的最后一件事是,估計的高度和寬度現(xiàn)在存儲在按相應(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. 計算器的高度(索引 0)和寬度(索引 1)(以像素為單位)。

          轉(zhuǎn)換為毫米

          但是,我們需要記住,圖 10 中的輸出仍然是像素數(shù)。要將這些值轉(zhuǎn)換為毫米,我們需要為此創(chuàng)建一個單獨的函數(shù),我將其命名為convert_to_mm()(Codeblock 17)。此函數(shù)通過取紙張長度(以毫米為單位)和像素(以像素為單位)的比率來工作。然后,我們可以通過將比率值(和)與仍以像素為單位的計算器大小(和#1#2相乘來獲得實際的毫米長度。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īng)成功獲得了邊緣的長度(以毫米為單位)。現(xiàn)在,我們將以文本的形式顯示這些值,這些文本寫在扭曲的圖像上。為此完成的整個過程都放在函數(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)容放在一個函數(shù)中

          由于我試圖解釋此項目中代碼使用的每個部分,因此我們上述執(zhí)行的所有步驟似乎很長。事實上,到目前為止您看到的所有代碼都可以包裝在一個函數(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)在就可以在幾個測試用例上測試它。圖 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é)果。

          一些局限

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

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

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

          交流群


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


          瀏覽 184
          10點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          10點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉网大香蕉网 | 免费的色情视频 | 亚洲欧美精品性爱 | 中文字幕网站 | 日韩福利视频 |