OpenCV已經將圖像處理(識別)的演算法寫成函數了,那我們還有必要去學習這些演算法不?

如題,本人剛開始學圖像識別一個星期,現在在學習使用OpenCV,然而我發現OpenCV已經把很多圖像識別所需要的演算法都寫好成函數了,比如邊緣檢測,輪廓檢測這些。

那既然這樣,咱們還去學這些演算法幹嘛呢?我們只需要這些演算法是幹嘛的,然後使用的時候直接調用即可了啊!

另外大家在實際開發中還需要去重寫這些演算法還是直接把OpenCV的源碼拿來用啊?

迷茫中,求大神解答!


看你最終需求是什麼。

如果是常規日常圖像處理,偶爾拿來作為編輯工具使用一下,我覺得只要基本了解一下演算法的功能然後拿來用就好了。比如說,你說的邊緣檢測濾鏡有好幾種,你至少得了解不同濾鏡的基本原理和優缺點。

當然,如果是想入圖像處理大坑,那麼在數學層面系統的理解一些常用演算法絕對是必不可少的。除了幫助你理解這些工具外,還可以幫助你打開腦洞,讓你的思維更加廣闊。再複雜的機器往往都是由許多簡單的零件堆疊而成的,一點一滴的基礎積累至關重要。


這也是很多開發過程中要糾結的一個問題,如果某一個功能已經有現成的庫,究竟用不用好呢(; ̄д ̄)

這些還是要看需求吧。如果是自己實現,會對這個演算法更加了解,可維護性和可控性會提高,還沒什麼開源協議的限制和束縛,實現演算法過程中順便滿足好奇心,特別你如果是做某個領域的東西,就算不需要去碰底層,懂得底層的原理還是很重要的。但是自己實現這些細節的話學習和開發成本會比較大,可能在實際工作中擔負不起這樣的成本,像我這些學生倒是無所謂,反正時間不值錢(逃。

所以在你不太需要了解底層,且第三方庫的開源協議適合,可以跟項目比較好的契合,那就用吧


blas已經將矩陣寫成函數了,我還學線代嗎?

mma已經可以解微分方程了,我還學微積分嗎?

不學你都不理解工具在幹嘛


「常若知其然而不知其所以然,欲摹寫其情狀,而心不能自喻,口不能自宣,筆不能自傳。」

出自梁啟超的《論小說與群治之關係》


第一次回答,不好的地方還請見諒。

這應該看題主現階段的能力和需求吧。還不清楚題主目前處在什麼狀態,我拿我自己來說,剛上大三的計算機學生,平時參加robocon競賽(門檻挺高的一個機器人比賽,有興趣的可以了解下),今年我們拿了個國際賽亞軍,8月份比完賽回來開始學習openCV,目標是在17年的比賽中使用視覺(不保證一定會用上)。我要學明白的原因主要有下面這兩個:

其一,robocon比賽對穩定性的要求非常高,所以我必須要把我所寫的程序弄的明明白白,如果我只是用了openCV的庫,在實際應用中出現了問題,我不太可能處理的很好。而且比賽場地可能環境比較複雜,需要針對場地做一些改變,如果我不懂原理,不懂其中的演算法怎麼可以。

其二,我們用的平台可能不允許,就拿今年的比賽來說,我們的一台機器人用了一款小攝像頭,處理器是ARM-M4,直接使用openCV不現實,如果我明白原理,我可以用c寫一個適合我的程序(我們也是這麼做的)。

為了學好這一些,我不僅要學會原理,還要能用代碼實現出來,現在學了有小一個月了,邊學邊自己邊實現一些演算法,自己仿著openCV寫了一個庫,Github上有:https://github.com/ffiirree/zMatrix,已經實現了中值、方框、高斯、均值濾波,基本的形態學濾波,還有Canny邊緣檢測演算法,不過演算法的實現還比較糙,沒有經過什麼優化,其他的還在實現中。

這些比較基礎,有些能力的都能實現,我現在實現的這幾種演算法可以在不同的平台自己再實現出來,更靈活,非常方便。

感覺只是學會使用其實應該不算邁入了圖像處理的大門吧,通過學習這些原理,實現演算法,感覺的確學到了很多東西,比剛上來只學習函數怎麼用好多了。

所以我覺得,有能力,有時間,必須要懂原理,學會這些演算法。


有必要,非常有必要。

既然你這麼問了,那我默認你是做圖像處理/機器學習方向的研究,或者你是程序員,但經常要接觸圖像相關的編程。

兩種情況下你都需要去了解他們的原理。

因為:

如果你讀過opencv的源碼,你就會發現,好多的演算法,它的實現效率是多麼地低!以及,他考慮的情況是多麼地少!

有時候為了性能,為了更好地應用到你的實際情況,必須要自己手動去實現一些演算法,或者更改opencv的源碼。

我舉一個簡單的小例子:

利用opencv的Laplace運算元對圖像進行邊緣檢測。

opencv的調用方式很簡單:

#include &
#include &

using namespace std;
using namespace cv;

int main()
{
Mat src = imread("test.jpg");
Mat dst;
Laplacian(src,dst,src.depth());
imshow("src",src);
imshow("result",dst);
waitKey(0);
return 0;
}

一句Laplacian(src,dst,src.depth())調用就搞定了,確實很簡單。效果也不錯:

查看它的源碼:

聲明部分

// .h
CV_EXPORTS_W void Laplacian( InputArray src, OutputArray dst, int ddepth,
int ksize=1, double scale=1, double delta=0,
int borderType=BORDER_DEFAULT );

實現部分:

// .cpp
void Laplacian(InputArray src, OutputArray dst, int ddepth, int ksize, double scale,
double delta, int borderType)
{
CV_Assert(delta == 0);

if (!src.clCxt-&>supportsFeature(FEATURE_CL_DOUBLE) src.type() == CV_64F)
{
CV_Error(CV_OpenCLDoubleNotSupported, "Selected device doesn"t support double");
return;
}

CV_Assert(ksize == 1 || ksize == 3);

double K[2][9] =
{
{0, 1, 0, 1, -4, 1, 0, 1, 0},
{2, 0, 2, 0, -8, 0, 2, 0, 2}
};
Mat kernel(3, 3, CV_64F, (void *)K[ksize == 3 ? 1 : 0]);

if (scale != 1)
kernel *= scale;

filter2D(src, dst, ddepth, kernel, Point(-1, -1), 0, borderType);
}

注意倒數第4句的ksize,它只考慮了兩個laplacian的掩膜(mask):

當ksize == 1時(默認值),選擇k[0],即掩膜為:

當ksize==3時,選擇k[1],掩膜為:

這兩個掩膜都是非常簡單的3x3的laplacian的掩膜,但是不是太簡單了!

如果我實際需要5x5的掩膜、7x7的掩膜呢?需要不同的掩膜參數呢?這些通過直接調用這個函數就做不到了,所以需要我們自己去寫源碼實現我們想要的功能。

(這個例子是從演算法實現角度去考慮的,另一個方面是實現效率上,也有很多可以優化的地方.)

所以,少年,勇敢地去了解演算法的原理吧:)


最近遇到一個問題,用opencv的庫,但是直接引到app里好大,這個東西咋裁剪縮小庫的大小,中間依賴關係是啥


opencv使用的方法都是最經典最常規最通用的。

這些方法用起來效果不錯,但是穩定性跟速度都沒法保障,當你要開發具體應用的時候,你還是需要結合你的處理對象訂製一些針對性的演算法,這個時候如果能使用opencv里的基礎方法進行組合,那是比較方便的,但如果不行,就只能自己寫了。

而且,學演算法的作用不僅是學會應用,也是在學習一種解決問題的思路,這也是圖像工作者的價值所在,所以還是好好學吧。


1.opencv沒有比較新的演算法。比如opencv做圖割,還是用的grab cut。這演算法04年的,現在是17年。稍微新一點的,比如11年的power watershed,以及稍早一點的continous max flow,據我所知除了作者的代碼(而且還不能直接用),opencv是沒有集成的。根據我平時使用的經驗,opencv的演算法基本都是08年以前的。而且很多學術界非常常用的演算法opencv都沒有,比如TV去噪(別TV了,PM都沒)。什麼是TV去噪,蘋果手機去噪演算法就用的這個,放大了非常明顯。比較可以接受的高速解法大概也就是11年12年那會兒出來的。所以我平時用opencv基本僅限於讀圖/取像素點/和做一些簡單的變換,比如圖片拉伸這種。新的演算法很多都是需要自己去implement的。

2.東西老,比如高斯模糊,幾十年前的,你能不學嗎?高斯模糊門道還多了。比如怎麼用離散的高斯去快速畢竟高斯核?怎麼提高高斯卷積的計算速度?高斯卷積核寬度取多少?怎麼用高斯卷積做多尺度?這不都是問題嗎。用了幾年OpenCV結果連卷積是什麼都搞不拎清,這不麻煩了。

3.OpenCV有些代碼是有BUG的。而且OpenCV有些代碼也根本沒有優化過。如果有這方面的需求還是要自己寫或者找更專業的庫。


看你想當一個代碼猴還是一個工程師。

調用一個函數,調調參數很簡單。門檻很低。

藍翔出來的也能幹。

但是你要是想做一些新的創新,就必須懂原理。知道他是怎麼工作的,為什麼工作,什麼情況下不適用,為什麼不工作,要如何改進才能工作。

雙邊濾波的作者一定知道高斯的原理。

勿在浮土築高台。


有。

計算機視覺很多演算法給的參數差這麼一點點,出來的結果可能差之千里。為了了解這些參數是做什麼用的、發揮什麼作用以及什麼樣的情況該用什麼樣的參數,這些都需要去學習了解演算法。


不深入學習裡面的演算法?

那你以後就只能這麼乾瞪眼看這個。。。


拋開需求談xx都是耍流氓


喜歡研究就看看原理和實現,覺得有心理負擔就等有心情了再研究,重要的是寫代碼要開心。有一點是,opencv里基本是基礎實現和經典演算法,最新成果基於它們之上。還有,opencv的大部分代碼實現兼顧簡潔靈活高效,很有參考價值,拿自己的實現和它對比,進步很快。


要知道我們在使用編程語言的時候,很多東西也已經封裝好了,比如vector,stack,queue...

但是我們還是要學習棧,隊列這些知識啊,對知識的掌握才能讓我們更好地去應用工具~


如果是小需求,那麼不需要深入理解,直接把opencv文檔看懂,學習些常見的問題就行了。

但是如果有深入的要求,比如從事相關研究或者精確度要求比較高的工程項目時,opencv的函數並不一定是最好的方法,畢竟選取的也都是些比較老而且穩定的演算法。自己新拿來一篇論文,要理解需要明白最根本的東西,就是opencv隱含的數學基礎等,要復現需要自己擼演算法,opencv的函數不一定合適。


說說我吧,我也剛為了項目學C++和OPENCV,以前我是C#陣營的,有時候真懶的學OPENCV自帶的那些演算法比如邊緣檢測的五個傳入參我到現在還沒整明白。我只會MAT a.at&(x,y),然後我循環遍歷像素做各種操作,比如我寫了高斯模糊,二值化,邊緣檢測,繪製矩形等等,而且就算是1080*1920的圖也是效率奇高,不比OPENCV自帶的演算法差,然後我把這些方法封到DLL里供WPF調用,供UNITY調用,我愛我的庫,就像不斷裝修一套屬於自己的房子,這種不斷完善的感覺很美妙,就像OPENGL的GLEW庫一樣,以後OPENCV會不會有我的庫出名了開源供給大家使用。

而且我還對項目有胸有成竹的感覺,因為我完全了解了它,忘記說了,我的項目是通過雙目攝像頭做採集點定位,我愛我的項目。所以我忽略了我的家人,媳婦帶著孩子回外省的老家一呆就是半年多。


感謝大家的回答,這個問題的答案已經非常明確了。

一句話總結出來就是:

你想用得越高級,那麼就該學習得越深入。


進行簡單應用是沒關係的,深層次應用就有問題了


我自己來了

我的目標很簡單,把opencv增加2d to 3d庫,而且保持跨平台性,那麼我必然要重構它啊


推薦閱讀:

用演算法怎樣識別圖片上的植物?
能否搜索某視頻的其中一幀畫面?或者通過一張圖片搜索此圖來自哪個視頻?
Facebook 的人工智慧實驗室 (FAIR) 有哪些厲害的大牛和技術積累?
先進的圖像識別怎樣改變 AV 產業?

TAG:圖像處理 | 圖像識別 | 深度學習DeepLearning |