<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>

          防抖技術(shù) | OpenCV實現(xiàn)視頻穩(wěn)流

          共 15640字,需瀏覽 32分鐘

           ·

          2021-05-25 16:30

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

          重磅干貨,第一時間送達

          本文轉(zhuǎn)自|OpenCV學(xué)堂

          這篇文章分享了一個視頻防抖的策略,這個方法同樣可以應(yīng)用到其他領(lǐng)域,比如常見的關(guān)鍵點檢測,當使用視頻測試時,效果就沒有demo那么好,此時可以考慮本文的方法去優(yōu)化。

          分享這些demo并不一定所有人都會用到,但是在解決實際問題的時候,可以提供一個思路去解決問題。希望能給我一個三連,鼓勵一下哈

          在這篇文章中,我們將學(xué)習(xí)如何使用OpenCV庫中的點特征匹配技術(shù)來實現(xiàn)一個簡單的視頻穩(wěn)定器。我們將討論算法并且會分享代碼(python和C++版),以使用這種方法在OpenCV中設(shè)計一個簡單的穩(wěn)定器。

          視頻中低頻攝像機運動的例子

          視頻防抖是指用于減少攝像機運動對最終視頻的影響的一系列方法。攝像機的運動可以是平移(比如沿著x、y、z方向上的運動)或旋轉(zhuǎn)(偏航、俯仰、翻滾)。

          視頻防抖的應(yīng)用

          對視頻防抖的需求在許多領(lǐng)域都有。

          這在消費者和專業(yè)攝像中是極其重要的。因此,存在許多不同的機械、光學(xué)和算法解決方案。即使在靜態(tài)圖像拍攝中,防抖技術(shù)也可以幫助拍攝長時間曝光的手持照片。

          在內(nèi)窺鏡和結(jié)腸鏡等醫(yī)療診斷應(yīng)用中,需要對視頻進行穩(wěn)定,以確定問題的確切位置和寬度。

          同樣,在軍事應(yīng)用中,無人機在偵察飛行中捕獲的視頻也需要進行穩(wěn)定,以便定位、導(dǎo)航、目標跟蹤等。同樣的道理也適用于機器人。

          視頻防抖的不同策略

          視頻防抖的方法包括機械穩(wěn)定方法、光學(xué)穩(wěn)定方法和數(shù)字穩(wěn)定方法。下面將簡要討論這些問題:

          機械視頻穩(wěn)定:機械圖像穩(wěn)定系統(tǒng)使用由特殊傳感器如陀螺儀和加速度計檢測到的運動來移動圖像傳感器以補償攝像機的運動。
          光學(xué)視頻穩(wěn)定:在這種方法中,不是移動整個攝像機,而是通過鏡頭的移動部分來實現(xiàn)穩(wěn)定。這種方法使用了一個可移動的鏡頭組合,當光通過相機的鏡頭系統(tǒng)時,可以可變地調(diào)整光的路徑長度。
          數(shù)字視頻穩(wěn)定:這種方法不需要特殊的傳感器來估計攝像機的運動。主要有三個步驟:1)運動估計2)運動平滑,3)圖像合成。第一步導(dǎo)出了兩個連續(xù)坐標系之間的變換參數(shù)。第二步過濾不需要的運動,在最后一步重建穩(wěn)定的視頻。
          在這篇文章中,我們將學(xué)習(xí)一個快速和魯棒性好的數(shù)字視頻穩(wěn)定算法的實現(xiàn)。它是基于二維運動模型,其中我們應(yīng)用歐幾里得(即相似性)變換包含平移、旋轉(zhuǎn)和縮放。

          OpenCV Motion Models

          正如你在上面的圖片中看到的,在歐幾里得運動模型中,圖像中的一個正方形可以轉(zhuǎn)換為任何其他位置、大小或旋轉(zhuǎn)不同的正方形。它比仿射變換和單應(yīng)變換限制更嚴格,但對于運動穩(wěn)定來說足夠了,因為攝像機在視頻連續(xù)幀之間的運動通常很小。

          使用點特征匹配實現(xiàn)視頻防抖

          該方法涉及跟蹤兩個連續(xù)幀之間的多個特征點。跟蹤特征允許我們估計幀之間的運動并對其進行補償。

          下面的流程圖顯示了基本步驟。

          我們來看看這些步驟。

          第一步:設(shè)置輸入和輸出視頻

          首先,讓我們完成讀取輸入視頻和寫入輸出視頻的設(shè)置。代碼中的注釋解釋每一行。

          Python

          # Import numpy and OpenCVimport numpy as npimport cv2
          # Read input videocap = cv2.VideoCapture('video.mp4')&nbsp;
          # Get frame countn_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
          # Get width and height of video streamw = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
          # Define the codec for output videofourcc = cv2.VideoWriter_fourcc(*'MJPG')
          # Set up output videoout = cv2.VideoWriter('video_out.mp4', fourcc, fps, (w, h))

          C++

           // Read input video  VideoCapture cap("video.mp4");
          // Get frame count int n_frames = int(cap.get(CAP_PROP_FRAME_COUNT));
          // Get width and height of video stream int w = int(cap.get(CAP_PROP_FRAME_WIDTH)); int h = int(cap.get(CAP_PROP_FRAME_HEIGHT));
          // Get frames per second (fps) double fps = cap.get(CV_CAP_PROP_FPS);
          // Set up output video VideoWriter out("video_out.avi", CV_FOURCC('M','J','P','G'), fps, Size(2 * w, h));


          第二步:讀取第一幀并將其轉(zhuǎn)換為灰度圖

          對于視頻穩(wěn)定,我們需要捕捉視頻的兩幀,估計幀之間的運動,最后校正運動。

          Python

          # Read first frame_, prev = cap.read() 
          # Convert frame to grayscaleprev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)

          C++

           // Define variable for storing frames  Mat curr, curr_gray;  Mat prev, prev_gray;
          // Read first frame cap &gt;&gt; prev;
          // Convert frame to grayscale cvtColor(prev, prev_gray, COLOR_BGR2GRAY);


          第三步:尋找?guī)g的移動

          這是算法中最關(guān)鍵的部分。我們將遍歷所有的幀,并找到當前幀和前一幀之間的移動。沒有必要知道每一個像素的運動。歐幾里得運動模型要求我們知道兩個坐標系中兩個點的運動。但是在實際應(yīng)用中,找到50-100個點的運動,然后用它們來穩(wěn)健地估計運動模型是一個好方法。

          3.1 可用于跟蹤的優(yōu)質(zhì)特征
          現(xiàn)在的問題是我們應(yīng)該選擇哪些點進行跟蹤。請記住,跟蹤算法使用一個小補丁圍繞一個點來跟蹤它。這樣的跟蹤算法受到孔徑問題的困擾,如下面的視頻所述

          因此,光滑的區(qū)域不利于跟蹤,而有很多角的紋理區(qū)域則比較好。幸運的是,OpenCV有一個快速的特征檢測器,可以檢測最適合跟蹤的特性。它被稱為goodFeaturesToTrack)

          3.2 Lucas-Kanade光流
          一旦我們在前一幀中找到好的特征,我們就可以使用Lucas-Kanade光流算法在下一幀中跟蹤它們。

          它是利用OpenCV中的calcOpticalFlowPyrLK函數(shù)實現(xiàn)的。在calcOpticalFlowPyrLK這個名字中,LK代表Lucas-Kanade,而Pyr代表金字塔。計算機視覺中的圖像金字塔是用來處理不同尺度(分辨率)的圖像的。

          由于各種原因,calcOpticalFlowPyrLK可能無法計算出所有點的運動。例如,當前幀的特征點可能會被下一幀的另一個對象遮擋。幸運的是,您將在下面的代碼中看到,calcOpticalFlowPyrLK中的狀態(tài)標志可以用來過濾掉這些值。

          3.3 估計運動
          回顧一下,在3.1步驟中,我們在前一幀中找到了一些好的特征。在步驟3.2中,我們使用光流來跟蹤特征。換句話說,我們已經(jīng)找到了特征在當前幀中的位置,并且我們已經(jīng)知道了特征在前一幀中的位置。所以我們可以使用這兩組點來找到映射前一個坐標系到當前坐標系的剛性(歐幾里德)變換。這是使用函數(shù)estimateRigidTransform完成的。

          一旦我們估計了運動,我們可以把它分解成x和y的平移和旋轉(zhuǎn)(角度)。我們將這些值存儲在一個數(shù)組中,這樣就可以平穩(wěn)地更改它們。

          下面的代碼將完成步驟3.1到3.3。請務(wù)必閱讀代碼中的注釋以進行后續(xù)操作。

          Python

          # Pre-define transformation-store arraytransforms = np.zeros((n_frames-1, 3), np.float32) 
          for i in range(n_frames-2): # Detect feature points in previous frame prev_pts = cv2.goodFeaturesToTrack(prev_gray, maxCorners=200, qualityLevel=0.01, minDistance=30, blockSize=3) # Read next frame success, curr = cap.read() if not success: break
          # Convert to grayscale curr_gray = cv2.cvtColor(curr, cv2.COLOR_BGR2GRAY)
          # Calculate optical flow (i.e. track feature points) curr_pts, status, err = cv2.calcOpticalFlowPyrLK(prev_gray, curr_gray, prev_pts, None)
          # Sanity check assert prev_pts.shape == curr_pts.shape
          # Filter only valid points idx = np.where(status==1)[0] prev_pts = prev_pts[idx] curr_pts = curr_pts[idx]
          #Find transformation matrix m = cv2.estimateRigidTransform(prev_pts, curr_pts, fullAffine=False) #will only work with OpenCV-3 or less # Extract traslation dx = m[0,2] dy = m[1,2]
          # Extract rotation angle da = np.arctan2(m[1,0], m[0,0]) # Store transformation transforms[i] = [dx,dy,da] # Move to next frame prev_gray = curr_gray
          print("Frame: " + str(i) + "/" + str(n_frames) + " - Tracked points : " + str(len(prev_pts)))

          C++

          在c++實現(xiàn)中,我們首先定義一些類來幫助我們存儲估計的運動向量。下面的TransformParam類存儲了運動信息(dx -運動在x中,dy -運動在y中,da -角度變化),并提供了一個方法getTransform來將該運動轉(zhuǎn)換為變換矩陣。

          struct TransformParam{  TransformParam() {}  TransformParam(double _dx, double _dy, double _da)   {      dx = _dx;      dy = _dy;      da = _da;  }
          double dx; double dy; double da; // angle
          void getTransform(Mat &amp;T){ // Reconstruct transformation matrix accordingly to new values T.at&lt;double&gt;(0,0) = cos(da); T.at&lt;double&gt;(0,1) = -sin(da); T.at&lt;double&gt;(1,0) = sin(da); T.at&lt;double&gt;(1,1) = cos(da);
          T.at&lt;double&gt;(0,2) = dx; T.at&lt;double&gt;(1,2) = dy; }};

          在下面的代碼中,我們循環(huán)視頻幀并執(zhí)行步驟3.1到3.3。

          // Pre-define transformation-store array  vector &lt;TransformParam&gt; transforms; 
          // Mat last_T;
          for(int i = 1; i &lt; n_frames-1; i++) { // Vector from previous and current feature points vector &lt;Point2f&gt; prev_pts, curr_pts;
          // Detect features in previous frame goodFeaturesToTrack(prev_gray, prev_pts, 200, 0.01, 30);
          // Read next frame bool success = cap.read(curr); if(!success) break; // Convert to grayscale cvtColor(curr, curr_gray, COLOR_BGR2GRAY);
          // Calculate optical flow (i.e. track feature points) vector &lt;uchar&gt; status; vector &lt;float&gt; err; calcOpticalFlowPyrLK(prev_gray, curr_gray, prev_pts, curr_pts, status, err);
          // Filter only valid points auto prev_it = prev_pts.begin(); auto curr_it = curr_pts.begin(); for(size_t k = 0; k &lt; status.size(); k++) { if(status[k]) { prev_it++; curr_it++; } else { prev_it = prev_pts.erase(prev_it); curr_it = curr_pts.erase(curr_it); } }
          // Find transformation matrix Mat T = estimateRigidTransform(prev_pts, curr_pts, false);
          // In rare cases no transform is found. // We'll just use the last known good transform. if(T.data == NULL) last_T.copyTo(T); T.copyTo(last_T);
          // Extract traslation double dx = T.at&lt;double&gt;(0,2); double dy = T.at&lt;double&gt;(1,2); // Extract rotation angle double da = atan2(T.at&lt;double&gt;(1,0), T.at&lt;double&gt;(0,0));
          // Store transformation transforms.push_back(TransformParam(dx, dy, da));
          // Move to next frame curr_gray.copyTo(prev_gray);
          cout &lt;&lt; "Frame: " &lt;&lt; i &lt;&lt; "/" &lt;&lt; n_frames &lt;&lt; " - Tracked points : " &lt;&lt; prev_pts.size() &lt;&lt; endl; }


          第四步:計算幀之間的平滑運動

          在前面的步驟中,我們估計幀之間的運動并將它們存儲在一個數(shù)組中。我們現(xiàn)在需要通過疊加上一步估計的微分運動來找到運動軌跡。

          步驟4.1:軌跡計算

          在這一步,我們將增加運動之間的幀來計算軌跡。我們的最終目標是平滑這條軌跡。

          Python 在Python中,可以很容易地使用numpy中的cumsum(累計和)來實現(xiàn)。

          # Compute trajectory using cumulative sum of transformationstrajectory = np.cumsum(transforms, axis=0

          C++

          在c++中,我們定義了一個名為Trajectory的結(jié)構(gòu)體來存儲轉(zhuǎn)換參數(shù)的累積和。

          struct Trajectory{    Trajectory() {}    Trajectory(double _x, double _y, double _a) {        x = _x;        y = _y;        a = _a;    }
          double x; double y; double a; // angle};

          C我們還定義了一個函數(shù)cumsum,它接受一個TransformParams 向量,并通過執(zhí)行微分運動dx、dy和da(角度)的累積和返回軌跡。

          vector&lt;Trajectory&gt; cumsum(vector&lt;TransformParam&gt; &amp;transforms){  vector &lt;Trajectory&gt; trajectory; // trajectory at all frames  // Accumulated frame to frame transform  double a = 0;  double x = 0;  double y = 0;
          for(size_t i=0; i &lt; transforms.size(); i++) { x += transforms[i].dx; y += transforms[i].dy; a += transforms[i].da;
          trajectory.push_back(Trajectory(x,y,a));
          }
          return trajectory; }

          步驟4.2:計算平滑軌跡

          在上一步中,我們計算了運動軌跡。所以我們有三條曲線來顯示運動(x, y,和角度)如何隨時間變化。

          在這一步,我們將展示如何平滑這三條曲線。

          平滑任何曲線最簡單的方法是使用移動平均濾波器(moving average filter)。顧名思義,移動平均過濾器將函數(shù)在某一點上的值替換為由窗口定義的其相鄰函數(shù)的平均值。讓我們看一個例子。

          假設(shè)我們在數(shù)組c中存儲了一條曲線,那么曲線上的點是c[0]…c[n-1]。設(shè)f是我們通過寬度為5的移動平均濾波器過濾c得到的平滑曲線。

          該曲線的k^{th}元素使用

          如您所見,平滑曲線的值是噪聲曲線在一個小窗口上的平均值。下圖顯示了左邊的噪點曲線的例子,使用右邊的尺度為5 濾波器進行平滑。

          Python

          在Python實現(xiàn)中,我們定義了一個移動平均濾波器,它接受任何曲線(即1-D的數(shù)字)作為輸入,并返回曲線的平滑版本。

          def movingAverage(curve, radius):   window_size = 2 * radius + 1  # Define the filter   f = np.ones(window_size)/window_size   # Add padding to the boundaries   curve_pad = np.lib.pad(curve, (radius, radius), 'edge')   # Apply convolution   curve_smoothed = np.convolve(curve_pad, f, mode='same')   # Remove padding   curve_smoothed = curve_smoothed[radius:-radius]  # return smoothed curve  return curve_smoothed

          我們還定義了一個函數(shù),它接受軌跡并對這三個部分進行平滑處理。

          def smooth(trajectory):   smoothed_trajectory = np.copy(trajectory)   # Filter the x, y and angle curves  for i in range(3):    smoothed_trajectory[:,i] = movingAverage(trajectory[:,i], radius=SMOOTHING_RADIUS)
          return smoothed_trajectory
          這是最后去使用
          # Compute trajectory using cumulative sum of transformationstrajectory = np.cumsum(transforms, axis=0)

          C++

          在c++版本中,我們定義了一個名為smooth的函數(shù),用于計算平滑移動平均軌跡。

          vector &lt;Trajectory&gt; smooth(vector &lt;Trajectory&gt;&amp; trajectory, int radius){  vector &lt;Trajectory&gt; smoothed_trajectory;   for(size_t i=0; i &lt; trajectory.size(); i++) {      double sum_x = 0;      double sum_y = 0;      double sum_a = 0;      int count = 0;
          for(int j=-radius; j &lt;= radius; j++) { if(i+j &gt;= 0 &amp;&amp; i+j &lt; trajectory.size()) { sum_x += trajectory[i+j].x; sum_y += trajectory[i+j].y; sum_a += trajectory[i+j].a;
          count++; } }
          double avg_a = sum_a / count; double avg_x = sum_x / count; double avg_y = sum_y / count;
          smoothed_trajectory.push_back(Trajectory(avg_x, avg_y, avg_a)); }
          return smoothed_trajectory; }


          我們在主函數(shù)中使用它

          // Smooth trajectory using moving average filter  vector &lt;Trajectory&gt; smoothed_trajectory = smooth(trajectory, SMOOTHING_RADIUS);


          步驟4.3:計算平滑變換
          到目前為止,我們已經(jīng)得到了一個平滑的軌跡。在這一步,我們將使用平滑的軌跡來獲得平滑的變換,可以應(yīng)用到視頻的幀來穩(wěn)定它。

          這是通過找到平滑軌跡和原始軌跡之間的差異,并將這些差異加回到原始的變換中來完成的。

          Python

          # Calculate difference in smoothed_trajectory and trajectorydifference = smoothed_trajectory - trajectory # Calculate newer transformation arraytransforms_smooth = transforms + difference

          C++

          vector <TransformParam> transforms_smooth;for(size_t i=0; i < transforms.size(); i++){// Calculate difference in smoothed_trajectory and trajectorydouble diff_x = smoothed_trajectory[i].x - trajectory[i].x;double diff_y = smoothed_trajectory[i].y - trajectory[i].y;double diff_a = smoothed_trajectory[i].a - trajectory[i].a;// Calculate newer transformation arraydouble dx = transforms[i].dx + diff_x;double dy = transforms[i].dy + diff_y;double da = transforms[i].da + diff_a;transforms_smooth.push_back(TransformParam(dx, dy, da));}
          第五步:將平滑的攝像機運動應(yīng)用到幀中

          差不多做完了。現(xiàn)在我們所需要做的就是循環(huán)幀并應(yīng)用我們剛剛計算的變換。

          如果我們有一個指定為(x, y, \theta),的運動,對應(yīng)的變換矩陣是

          請閱讀代碼中的注釋以進行后續(xù)操作。

          Python

          # Reset stream to first frame cap.set(cv2.CAP_PROP_POS_FRAMES, 0)  # Write n_frames-1 transformed framesfor i in range(n_frames-2):  # Read next frame  success, frame = cap.read()   if not success:    break
          # Extract transformations from the new transformation array dx = transforms_smooth[i,0] dy = transforms_smooth[i,1] da = transforms_smooth[i,2]
          # Reconstruct transformation matrix accordingly to new values m = np.zeros((2,3), np.float32) m[0,0] = np.cos(da) m[0,1] = -np.sin(da) m[1,0] = np.sin(da) m[1,1] = np.cos(da) m[0,2] = dx m[1,2] = dy
          # Apply affine wrapping to the given frame frame_stabilized = cv2.warpAffine(frame, m, (w,h))
          # Fix border artifacts frame_stabilized = fixBorder(frame_stabilized)
          # Write the frame to the file frame_out = cv2.hconcat([frame, frame_stabilized])
          # If the image is too big, resize it. if(frame_out.shape[1] &gt; 1920): frame_out = cv2.resize(frame_out, (frame_out.shape[1]/2, frame_out.shape[0]/2)); cv2.imshow("Before and After", frame_out) cv2.waitKey(10) out.write(frame_out)


          C++

          cap.set(CV_CAP_PROP_POS_FRAMES, 1);Mat T(2,3,CV_64F);Mat frame, frame_stabilized, frame_out; 

          for( int i = 0; i &lt; n_frames-1; i++) { bool success = cap.read(frame); if(!success) break; // Extract transform from translation and rotation angle. transforms_smooth[i].getTransform(T); // Apply affine wrapping to the given frame warpAffine(frame, frame_stabilized, T, frame.size()); // Scale image to remove black border artifact fixBorder(frame_stabilized); // Now draw the original and stabilised side by side for coolness hconcat(frame, frame_stabilized, frame_out); // If the image is too big, resize it. if(frame_out.cols &gt; 1920) { resize(frame_out, frame_out, Size(frame_out.cols/2, frame_out.rows/2)); }
          imshow("Before and After", frame_out); out.write(frame_out); waitKey(10);}


          步驟5.1:修復(fù)邊界偽影
          當我們穩(wěn)定一個視頻,我們可能會看到一些黑色的邊界偽影。這是意料之中的,因為為了穩(wěn)定視頻,幀可能不得不縮小大小。

          我們可以通過將視頻的中心縮小一小部分(例如4%)來緩解這個問題。

          下面的fixBorder函數(shù)顯示了實現(xiàn)。我們使用getRotationMatrix2D,因為它在不移動圖像中心的情況下縮放和旋轉(zhuǎn)圖像。我們所需要做的就是調(diào)用這個函數(shù)時,旋轉(zhuǎn)為0,縮放為1.04(也就是提升4%)。

          Python

          def fixBorder(frame):  s = frame.shape  # Scale the image 4% without moving the center  T = cv2.getRotationMatrix2D((s[1]/2, s[0]/2), 0, 1.04)  frame = cv2.warpAffine(frame, T, (s[1], s[0]))  return frame


          C++

          void fixBorder(Mat &frame_stabilized){Mat T = getRotationvoid fixBorder(Mat &amp;frame_stabilized){  Mat T = getRotationMatrix2D(Point2f(frame_stabilized.cols/2, frame_stabilized.rows/2), 0, 1.04);   warpAffine(frame_stabilized, frame_stabilized, T, frame_stabilized.size()); }Matrix2D(Point2f(frame_stabilized.cols/2, frame_stabilized.rows/2), 0, 1.04);warpAffine(frame_stabilized, frame_stabilized, T, frame_stabilized.size());}

          結(jié)果:

          我們分享的視頻防抖代碼的結(jié)果如上所示。我們的目標是顯著減少運動,但不是完全消除它。

          我們留給讀者去思考如何修改代碼來完全消除幀之間的移動。如果你試圖消除所有的相機運動,會有什么副作用?

          目前的方法只適用于固定長度的視頻,而不適用于實時feed。我們不得不對這個方法進行大量修改,以獲得實時視頻輸出,這超出了本文的范圍,但這是可以實現(xiàn)的,更多的信息可以在這里找到。

          https://abhitronix.github.io/2018/11/30/humanoid-AEAM-3/

          優(yōu)點和缺點

          優(yōu)點

          這種方法對低頻運動(較慢的振動)具有良好的穩(wěn)定性。這種方法內(nèi)存消耗低,因此非常適合嵌入式設(shè)備(如樹莓派)。這種方法對視頻縮放抖動有很好的效果。

          缺點

          這種方法對高頻擾動的抵抗效果很差。如果有一個嚴重的運動模糊,特征跟蹤將失敗,結(jié)果將不是最佳的。這種方法也不適用于滾動快門失真。

          References:

          1. Example video and Code reference from Nghia Ho’s post

            http://nghiaho.com/uploads/code/videostab.cpp

          2. Various References, data, and image from my website

            https://abhitronix.github.io/

          3. https://www.learnopencv.com/video-stabilization-using-point-feature-matching-in-opencv/


          下載1:OpenCV-Contrib擴展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

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

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

          交流群


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


          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  五月天色色网址 | 黄频AV | 最新黄色做爱在钱网站 | 派遣素描模特儿居家作画 却假藉 | 久久黄色樱桃视频 |