基於OpenCV的三種光流演算法實現原始碼及測試結果
本文包括基於OpenCV的三種光流演算法的實現原始碼及測試結果。具體為HS演算法,LK演算法,和ctfLK演算法,演算法的原實現作者是Eric Yuan,這裡是作者的部落格主頁:http://eric-yuan.me。本文對這三種光流演算法進行了相關除錯及結果驗證,供大家參考。
1. 第一種:HS光流法(作者HORN 和SCHUNCK)
#include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <math.h> #include <fstream> #include <iostream> using namespace cv; using namespace std; #define ATD at<double> #define elif else if #ifndef bool #define bool int #define false ((bool)0) #define true ((bool)1) #endif Mat get_fx(Mat &src1, Mat &src2){ Mat fx; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(1, 0) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fx = dst1 + dst2; return fx; } Mat get_fy(Mat &src1, Mat &src2){ Mat fy; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(0, 1) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fy = dst1 + dst2; return fy; } Mat get_ft(Mat &src1, Mat &src2){ Mat ft; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel = kernel.mul(-1); Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); kernel = kernel.mul(-1); filter2D(src2, dst2, -1, kernel); ft = dst1 + dst2; return ft; } bool isInsideImage(int y, int x, Mat &m){ int width = m.cols; int height = m.rows; if (x >= 0 && x < width && y >= 0 && y < height) return true; else return false; } double get_Average4(Mat &m, int y, int x){ if (x < 0 || x >= m.cols) return 0; if (y < 0 || y >= m.rows) return 0; double val = 0.0; int tmp = 0; if (isInsideImage(y - 1, x, m)){ ++tmp; val += m.ATD(y - 1, x); } if (isInsideImage(y + 1, x, m)){ ++tmp; val += m.ATD(y + 1, x); } if (isInsideImage(y, x - 1, m)){ ++tmp; val += m.ATD(y, x - 1); } if (isInsideImage(y, x + 1, m)){ ++tmp; val += m.ATD(y, x + 1); } return val / tmp; } Mat get_Average4_Mat(Mat &m){ Mat res = Mat::zeros(m.rows, m.cols, CV_64FC1); for (int i = 0; i < m.rows; i++){ for (int j = 0; j < m.cols; j++){ res.ATD(i, j) = get_Average4(m, i, j); } } return res; } void saveMat(Mat &M, string s){ s += ".txt"; FILE *pOut = fopen(s.c_str(), "w+"); for (int i = 0; i<M.rows; i++){ for (int j = 0; j<M.cols; j++){ fprintf(pOut, "%lf", M.ATD(i, j)); if (j == M.cols - 1) fprintf(pOut, "\n"); else fprintf(pOut, " "); } } fclose(pOut); } void getHornSchunckOpticalFlow(Mat img1, Mat img2){ double lambda = 0.05; Mat u = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat v = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat fx = get_fx(img1, img2); Mat fy = get_fy(img1, img2); Mat ft = get_ft(img1, img2); int i = 0; double last = 0.0; while (1){ Mat Uav = get_Average4_Mat(u); Mat Vav = get_Average4_Mat(v); Mat P = fx.mul(Uav) + fy.mul(Vav) + ft; Mat D = fx.mul(fx) + fy.mul(fy) + lambda; Mat tmp; divide(P, D, tmp); Mat utmp, vtmp; utmp = Uav - fx.mul(tmp); vtmp = Vav - fy.mul(tmp); Mat eq = fx.mul(utmp) + fy.mul(vtmp) + ft; double thistime = mean(eq)[0]; cout << "i = " << i << ", mean = " << thistime << endl; if (i != 0 && fabs(last) <= fabs(thistime)) break; i++; last = thistime; u = utmp; v = vtmp; } saveMat(u, "U"); saveMat(v, "V"); imshow("U", u); imshow("v", v); waitKey(20000); } int main(){ Mat img1 = imread("table1.jpg", 0); Mat img2 = imread("table2.jpg", 0); img1.convertTo(img1, CV_64FC1, 1.0 / 255, 0); img2.convertTo(img2, CV_64FC1, 1.0 / 255, 0); getHornSchunckOpticalFlow(img1, img2); // waitKey(0); return 0; }
圖1 HS光流法原始影象(之一)
圖2:HS光流法計算結果:U
圖3 HS光流法計算結果:V
1. 第二種:LK光流法(作者LUCAS 和KANADE)
#include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <math.h> #include <fstream> #include <iostream> using namespace cv; using namespace std; #define ATD at<double> #define elif else if #ifndef bool #define bool int #define false ((bool)0) #define true ((bool)1) #endif Mat get_fx(Mat &src1, Mat &src2){ Mat fx; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(1, 0) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fx = dst1 + dst2; return fx; } Mat get_fy(Mat &src1, Mat &src2){ Mat fy; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(0, 1) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fy = dst1 + dst2; return fy; } Mat get_ft(Mat &src1, Mat &src2){ Mat ft; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel = kernel.mul(-1); Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); kernel = kernel.mul(-1); filter2D(src2, dst2, -1, kernel); ft = dst1 + dst2; return ft; } bool isInsideImage(int y, int x, Mat &m){ int width = m.cols; int height = m.rows; if (x >= 0 && x < width && y >= 0 && y < height) return true; else return false; } double get_Sum9(Mat &m, int y, int x){ if (x < 0 || x >= m.cols) return 0; if (y < 0 || y >= m.rows) return 0; double val = 0.0; int tmp = 0; if (isInsideImage(y - 1, x - 1, m)){ ++tmp; val += m.ATD(y - 1, x - 1); } if (isInsideImage(y - 1, x, m)){ ++tmp; val += m.ATD(y - 1, x); } if (isInsideImage(y - 1, x + 1, m)){ ++tmp; val += m.ATD(y - 1, x + 1); } if (isInsideImage(y, x - 1, m)){ ++tmp; val += m.ATD(y, x - 1); } if (isInsideImage(y, x, m)){ ++tmp; val += m.ATD(y, x); } if (isInsideImage(y, x + 1, m)){ ++tmp; val += m.ATD(y, x + 1); } if (isInsideImage(y + 1, x - 1, m)){ ++tmp; val += m.ATD(y + 1, x - 1); } if (isInsideImage(y + 1, x, m)){ ++tmp; val += m.ATD(y + 1, x); } if (isInsideImage(y + 1, x + 1, m)){ ++tmp; val += m.ATD(y + 1, x + 1); } if (tmp == 9) return val; else return m.ATD(y, x) * 9; } Mat get_Sum9_Mat(Mat &m){ Mat res = Mat::zeros(m.rows, m.cols, CV_64FC1); for (int i = 1; i < m.rows - 1; i++){ for (int j = 1; j < m.cols - 1; j++){ res.ATD(i, j) = get_Sum9(m, i, j); } } return res; } void saveMat(Mat &M, string s){ s += ".txt"; FILE *pOut = fopen(s.c_str(), "w+"); for (int i = 0; i<M.rows; i++){ for (int j = 0; j<M.cols; j++){ fprintf(pOut, "%lf", M.ATD(i, j)); if (j == M.cols - 1) fprintf(pOut, "\n"); else fprintf(pOut, " "); } } fclose(pOut); } void getLucasKanadeOpticalFlow(Mat &img1, Mat &img2, Mat &u, Mat &v){ Mat fx = get_fx(img1, img2); Mat fy = get_fy(img1, img2); Mat ft = get_ft(img1, img2); Mat fx2 = fx.mul(fx); Mat fy2 = fy.mul(fy); Mat fxfy = fx.mul(fy); Mat fxft = fx.mul(ft); Mat fyft = fy.mul(ft); Mat sumfx2 = get_Sum9_Mat(fx2); Mat sumfy2 = get_Sum9_Mat(fy2); Mat sumfxft = get_Sum9_Mat(fxft); Mat sumfxfy = get_Sum9_Mat(fxfy); Mat sumfyft = get_Sum9_Mat(fyft); Mat tmp = sumfx2.mul(sumfy2) - sumfxfy.mul(sumfxfy); u = sumfxfy.mul(sumfyft) - sumfy2.mul(sumfxft); v = sumfxft.mul(sumfxfy) - sumfx2.mul(sumfyft); divide(u, tmp, u); divide(v, tmp, v); saveMat(u, "U"); saveMat(v, "V"); imshow("U", u); imshow("V", v); waitKey(2000); } int main(){ Mat img1 = imread("car1.jpg", 0); Mat img2 = imread("car2.jpg", 0); img1.convertTo(img1, CV_64FC1, 1.0 / 255, 0); img2.convertTo(img2, CV_64FC1, 1.0 / 255, 0); Mat u = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat v = Mat::zeros(img1.rows, img1.cols, CV_64FC1); getLucasKanadeOpticalFlow(img1, img2, u, v); cout << "done" << endl; return 0; }
圖4 LK光流法原始影象(之一)
圖5 LK光流法計算結果:U
圖6 LK光流法計算結果:V
1. 第三種:ctfLK光流法(LK光流法的Coarse to fine版本)
#include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <math.h> #include <fstream> #include <iostream> using namespace cv; using namespace std; #define ATD at<double> #define ATF at<float> #define elif else if #ifndef bool #define bool int #define false ((bool)0) #define true ((bool)1) #endif Mat get_fx(Mat &src1, Mat &src2){ Mat fx; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(1, 0) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fx = dst1 + dst2; return fx; } Mat get_fy(Mat &src1, Mat &src2){ Mat fy; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel.ATD(0, 0) = -1.0; kernel.ATD(0, 1) = -1.0; Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); filter2D(src2, dst2, -1, kernel); fy = dst1 + dst2; return fy; } Mat get_ft(Mat &src1, Mat &src2){ Mat ft; Mat kernel = Mat::ones(2, 2, CV_64FC1); kernel = kernel.mul(-1); Mat dst1, dst2; filter2D(src1, dst1, -1, kernel); kernel = kernel.mul(-1); filter2D(src2, dst2, -1, kernel); ft = dst1 + dst2; return ft; } bool isInsideImage(int y, int x, Mat &m){ int width = m.cols; int height = m.rows; if (x >= 0 && x < width && y >= 0 && y < height) return true; else return false; } double get_Sum9(Mat &m, int y, int x){ if (x < 0 || x >= m.cols) return 0; if (y < 0 || y >= m.rows) return 0; double val = 0.0; int tmp = 0; for (int i = -1; i <= 1; i++){ for (int j = -1; j <= 1; j++){ if (isInsideImage(y + i, x + j, m)){ ++tmp; val += m.ATD(y + i, x + j); } } } if (tmp == 9) return val; else return m.ATD(y, x) * 9; } Mat get_Sum9_Mat(Mat &m){ Mat res = Mat::zeros(m.rows, m.cols, CV_64FC1); for (int i = 1; i < m.rows - 1; i++){ for (int j = 1; j < m.cols - 1; j++){ res.ATD(i, j) = get_Sum9(m, i, j); } } return res; } void saveMat(Mat &M, string s){ s += ".txt"; FILE *pOut = fopen(s.c_str(), "w+"); for (int i = 0; i<M.rows; i++){ for (int j = 0; j<M.cols; j++){ fprintf(pOut, "%lf", M.ATD(i, j)); if (j == M.cols - 1) fprintf(pOut, "\n"); else fprintf(pOut, " "); } } fclose(pOut); } void getLucasKanadeOpticalFlow(Mat &img1, Mat &img2, Mat &u, Mat &v){ Mat fx = get_fx(img1, img2); Mat fy = get_fy(img1, img2); Mat ft = get_ft(img1, img2); Mat fx2 = fx.mul(fx); Mat fy2 = fy.mul(fy); Mat fxfy = fx.mul(fy); Mat fxft = fx.mul(ft); Mat fyft = fy.mul(ft); Mat sumfx2 = get_Sum9_Mat(fx2); Mat sumfy2 = get_Sum9_Mat(fy2); Mat sumfxft = get_Sum9_Mat(fxft); Mat sumfxfy = get_Sum9_Mat(fxfy); Mat sumfyft = get_Sum9_Mat(fyft); Mat tmp = sumfx2.mul(sumfy2) - sumfxfy.mul(sumfxfy); u = sumfxfy.mul(sumfyft) - sumfy2.mul(sumfxft); v = sumfxft.mul(sumfxfy) - sumfx2.mul(sumfyft); divide(u, tmp, u); divide(v, tmp, v); } vector<Mat> getGaussianPyramid(Mat &img, int nLevels){ vector<Mat> pyr; pyr.push_back(img); for (int i = 0; i < nLevels - 1; i++){ Mat tmp; pyrDown(pyr[pyr.size() - 1], tmp); pyr.push_back(tmp); } return pyr; } void coarseToFineEstimation(Mat &img1, Mat &img2, Mat &u, Mat &v, int nLevels){ vector<Mat> pyr1 = getGaussianPyramid(img1, nLevels); vector<Mat> pyr2 = getGaussianPyramid(img2, nLevels); Mat upu, upv; for (int i = nLevels - 1; i >= 0; i--){ Mat tmpu = Mat::zeros(pyr1[i].rows, pyr1[i].cols, CV_64FC1); Mat tmpv = Mat::zeros(pyr2[i].rows, pyr2[i].cols, CV_64FC1); getLucasKanadeOpticalFlow(pyr1[i], pyr2[i], tmpu, tmpv); if (i != nLevels - 1){ tmpu += upu; tmpv += upv; } if (i == 0){ u = tmpu; v = tmpv; return; } pyrUp(tmpu, upu); pyrUp(tmpv, upv); Mat map1(upu.size(), CV_32FC2); Mat map2(upu.size(), CV_32FC2); for (int y = 0; y < map1.rows; ++y){ for (int x = 0; x < map1.cols; ++x){ Point2f f = Point2f((float)(upu.ATD(y, x)), (float)(upv.ATD(y, x))); map1.at<Point2f>(y, x) = Point2f(x + f.x / 2, y + f.y / 2); map2.at<Point2f>(y, x) = Point2f(x - f.x / 2, y - f.y / 2); } } Mat warped1, warped2; remap(pyr1[i - 1], warped1, map1, cv::Mat(), INTER_LINEAR); remap(pyr2[i - 1], warped2, map2, cv::Mat(), INTER_LINEAR); warped1.copyTo(pyr1[i - 1]); warped2.copyTo(pyr2[i - 1]); } } int getMaxLayer(Mat &img){ int width = img.cols; int height = img.rows; int res = 1; int p = 1; while (1){ int tmp = pow(2, p); if (width % tmp == 0) ++p; else break; } res = p; p = 1; while (1){ int tmp = pow(2, p); if (height % tmp == 0) ++p; else break; } res = res < p ? res : p; return res; } int main(){ Mat ori1 = imread("table1.jpg", 0); Mat ori2 = imread("table2.jpg", 0); Mat img1 = ori1(Rect(0, 0, 640, 448)); Mat img2 = ori2(Rect(0, 0, 640, 448)); int maxLayer = getMaxLayer(img1); cout << img1.rows << ", " << img1.cols << ", Max layer = " << maxLayer << endl; img1.convertTo(img1, CV_64FC1, 1.0 / 255, 0); img2.convertTo(img2, CV_64FC1, 1.0 / 255, 0); Mat u = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat v = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat u2 = Mat::zeros(img1.rows, img1.cols, CV_64FC1); Mat v2 = Mat::zeros(img1.rows, img1.cols, CV_64FC1); if (maxLayer >= 1){ coarseToFineEstimation(img1, img2, u, v, maxLayer); saveMat(u, "U"); saveMat(v, "V"); } getLucasKanadeOpticalFlow(img1, img2, u2, v2); saveMat(u2, "U2"); saveMat(v2, "V2"); imshow("U2", u2); imshow("v2", v2); waitKey(20000); return 0; }
圖7 ctfLK光流法測試原始影象(之一)
圖8 ctfLK光流法計算結果:U2
圖9 ctfLK光流法計算結果:v2
相關推薦
基於OpenCV的三種光流演算法實現原始碼及測試結果
本文包括基於OpenCV的三種光流演算法的實現原始碼及測試結果。具體為HS演算法,LK演算法,和ctfLK演算法,演算法的原實現作者是Eric Yuan,這裡是作者的部落格主頁:http://eric-yuan.me。本文對這三種光流演算法進行了相關除錯及結果驗證,供大家
解決尋找第K小元素問題——三種不同的演算法實現
問題描述:在一個序列裡找出第K小元素 以下程式基於函式 int select_kth_smallest(list q, int k) 實現 :返回向量q中第k最小元的函式 演算法一: 基於氣泡排序思想,暴力求解: 基本思路:要求找出第k個最小元素,可以通過在序
玩轉OpenCV 4.0(一):呼叫Dis光流演算法示例
玩轉OpenCV 4.0(一):呼叫Dis光流演算法示例 呼叫DIS光流的原始碼如下: 對應CMakelists如下: 呼叫DIS光流的原始碼如下: #include "opencv2/core/utility.hpp"
Java實現二叉樹三種遍歷演算法
</pre><p></p><p>參考網上一些資料測試整理了一下二叉樹遍歷的Java實現程式碼。</p>二叉樹三種遍歷方式:先序遍歷、中序遍歷、後序遍歷。<p>首先定義二叉樹類:</p>&l
java實現二叉樹的三種遍歷演算法(遞迴)
一,定義一個節點類: package test; public class Node { private int data; private Node left; private Node right; public Node(int data) { thi
三種常用排序演算法(冒泡、選擇、快速)的Java實現
學習Java有一陣子了,現在還處於比較初級的水平,能夠把簡單的程式寫對就不錯了,更不用談現在能夠拿Java做什麼了。 學完了兩段網路視訊課程,接下來找本書簡單看看。只要有了一個初步的認識,接下來的東西應該可以更加順利一些。學習程式設計最好的方法就
鳶尾花三種聚類演算法(K-means,AGNES,DBScan)的python實現
一.分散性聚類(kmeans) 演算法流程: 1.選擇聚類的個數k. 2.任意產生k個聚類,然後確定聚類中心,或者直接生成k箇中心。 3.對每個點確定其聚類中心點。 4.再計算其聚類新中心。 5.重複以上步驟直到滿足收斂要求。(通常就是確定的中心點不再改變。
目標檢測光流法(二):opencv下的光流L-K演算法
後續將簡單介紹光流法的一些簡單實現包,包括opencv下的光流演算法與matlab下的光流演算法。該節主要介紹opencv下的光流實現。 Opencv的光流實現由好幾個方法可以(也就是說有好幾個函式可以用),每個函式當然也對應著不同的原理,那麼它的效果以及演算
三種快速排序演算法的實現(遞迴演算法、非遞迴演算法、三路劃分快速排序)
快速排序的三個步驟: 1、分解:將陣列A[l...r]劃分成兩個(可能空)子陣列A[l...p-1]和A[p+1...r],使得A[l...p-1]中的每個元素都小於等於A(p),而且,小於等於A[p
OpenCV 光流演算法加速---使用GPU來計算光流
一、依賴項 OpenCV 2.4.13.x + CUDA 8.0 OpenCV 3.2.0及以上 + CUDA 8.0 OpenCV 3.4.x + CUDA 9.1 OpenCV編譯時,需要新增CUDA 支援。安裝CUDA 以及OpenCV,可參考我的另外兩篇部落格
DES/3DES/AES 三種對稱加密演算法在 Java 中的實現
有兩句話是這麼說的:1)演算法和資料結構就是程式設計的一個重要部分,你若失掉了演算法和資料結構,你就把一切都失掉了。2)程式設計就是演算法和資料結構,演算法和資料結構是程式設計的靈魂。注意,這可不是我說的,是無數程式設計師總結的,話說的很實在也很精闢,若想長久可持續發展,多研
nginx虛擬主機三種模式的簡單實現
_for nod send nop request user 模式 -s hit main配置段: user nginx; #指定用於運行worker進程的用戶和組 worker_processes 4; #worker的進程數;通常應該為CPU的核心數或核心數減1
035捷聯慣導中三種姿態更新演算法說明
看到了不同的姿態更新演算法,很迷惑,陷入了誰相對於誰的思考中。翻翻嚴老師部落格,貼出來如下: 原文地址:http://blog.sina.com.cn/s/blog_40edfdc90102v6il.html#cmt_556E9C77-7F000001-41D46DB9-790-8
Lucas–Kanade光流演算法學習
Lucas–Kanade光流演算法是一種兩幀差分的光流估計演算法。它由Bruce D. Lucas 和 Takeo Kanade提出。 光流(Optical flow or optic
opencv三種線性濾波的綜合使用
本文程式碼來源於https://blog.csdn.net/poem_qianmo/article/details/22745559,在上一篇文章的基礎上增加了進度條的支援,可以更加直觀的看出濾波的效果 #include "widget.h" #include <QApplication&
jvm 三種垃圾回收演算法:標記-清除、複製演算法、標記-整理
標記-清除:先標記出GC Roots能關聯到的物件,然後清除這些被標記的物件,剩下的就是存活的物件了。 缺點: 1、清除需要被清理的物件後剩下的記憶體都是破碎的,如果要建立大物件,可能會因為找不到足夠的記憶體而再次觸發垃圾收集。 2、標記和清除的效率相對於其他演算法來說都不高,標記的原理
java三種代理模式的實現
1、什麼是代理模式 代理模式:就是為其他物件提供一種代理以控制對這個物件的訪問。 代理可以在不改動目標物件的基礎上,增加其他額外的功能(擴充套件功能)。 舉個例子來說明代理的作用: 一般我們想邀請明星來當我們的代言人,我們並不能直接聯絡到明星,而是通過其經紀人,來告訴經紀人我們需要
【演算法分析】Lucas–Kanade光流演算法
作者:[email protected]簡介:在計算機視覺中,Lucas–Kanade光流演算法是一種兩幀差分的光流估計演算法。它由Bruce D. Lucas 和 Takeo Kanade提出。光流的概念:(Optical flow or optic flow)它是一種運動模式,這種運動模式指的是
基於聚類(Kmeans)演算法實現客戶價值分析系統(電信運營商)
開發環境 jupyter notebook 一、電信運營商–客戶價值分析 從客戶需求出發,瞭解客戶需要什麼,他們有怎麼樣的特徵, 電信運營商為客戶設定不同的優惠套餐 爭取更多的使用者:推出不同的優
深度學習(三)——tiny YOLO演算法實現實時目標檢測(tensorflow實現)
一、背景介紹 YOLO演算法全稱You Only Look Once,是Joseph Redmon等人於15年3月發表的一篇文章。本實驗目標為實現YOLO演算法,借鑑了一部分材料,最終實現了輕量級的簡化版YOLO——tiny YOLO,其優勢在於實現簡單,目標檢測迅速。 [1]文章連結:ht