OpenCV 3.2.0 已經在 2016/12/23 公開發行. 除了一些問題的修正外, 這一個版本的 Windows 版本是在 VC14, 也就是 Visual Studio 2015. 剛好接下來的工作也議定在 Visual Studio 2015 Community 上開發, 於是就選定用這個版本. 這個版本的使用上, 遇到的一些問題, 做個紀錄.
尼克工作中
2017年5月16日 星期二
[OpenCV] 3.2.0 實裝心得
OpenCV 3.2.0 已經在 2016/12/23 公開發行. 除了一些問題的修正外, 這一個版本的 Windows 版本是在 VC14, 也就是 Visual Studio 2015. 剛好接下來的工作也議定在 Visual Studio 2015 Community 上開發, 於是就選定用這個版本. 這個版本的使用上, 遇到的一些問題, 做個紀錄.
2017年4月10日 星期一
[VideoInput] Download
Download VideoInput Libray from GitHub
https://github.com/ofTheo/videoInput to D://VideoInputExtract
Synchronize project setting
Modification for Visual Studio 2015
VideoInput.cpp Line 821 aschar * name = (char*) videoInput::getDeviceName(i);
2017年4月9日 星期日
[OpenCV] Using OpenCV static library in MFC application
Create MFC Application
Add Picture Control
Add Initial codes in OnInitDialog
// TODO: Add extra initialization hereCRect rect;
CWnd *pWnd = GetDlgItem(IDC_LIVE);
pWnd->GetWindowRect(&rect);
ScreenToClient(&rect); //optional step - see below
cv::namedWindow("IDC_STATIC_OUTPUT", 0);
cvResizeWindow("IDC_STATIC_OUTPUT", rect.right - rect.left, rect.bottom - rect.top);
HWND hWnd = (HWND)cvGetWindowHandle("IDC_STATIC_OUTPUT");
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_LIVE)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
if (m_video.open(0))
{
SetTimer(0, 33, NULL);
}
Add OnTimer Handler to drawing
void COpenCV_Static_MFCDlg::OnTimer(UINT_PTR nIDEvent)
{
// TODO: Add your message handler code here and/or call default
cv::Mat frame;
m_video >> frame;
cv::imshow("IDC_STATIC_OUTPUT", frame);
CDialogEx::OnTimer(nIDEvent);
}
Update project setting
/Configuration Prperties/General
Use of MFC –> Use MFC in a Static Librar/Configuration Properties/C/C++/Code Generation
Character Set –> Use Multi-Byte Character Set
Runtime Library –> Multi-thread (/MT)/Configuration Properties/VC++ Directories
Security Check –> Disable Security Check (/GS-)
Include Directories: D:\OpenCV-3.2.0\opencv\build\include/Configuration Properties/Linker/Input
Library Directires
Additional Dependencies
opencv_highgui320.lib
opencv_core320.lib
ippicvmt.lib
zlib.lib
opencv_imgproc320.lib
opencv_imgcodecs320.lib
IlmImf.lib
libjpeg.lib
libjasper.lib
libpng.lib
libtiff.lib
libwebp.lib
opencv_video320.lib
opencv_videoio320.lib
vfw32.lib
[OpenCV] Using static library in Visual Studio 2015 Console mode
Create Visual Studio 2015 console program
Add VideoCapture calls
#include "stdafx.h"#include <opencv2/opencv.hpp>
int main()
{
cv::Mat frame;
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
return -1;
}
while (true) {
if (!cap.read(frame))
break;
cv::Mat src = cv::Mat(frame);
cv::imshow("window", src);
cv::waitKey(30);
}
}
Add OpenCV include path
D:\OpenCV-3.2.0\opencv\build\includeAdd OpenCV library path
D:\OpenCV-3.2.0\opencv\build\x86-static\lib\ReleaseD:\OpenCV-3.2.0\opencv\build\x86-static\3rdparty\ippicv\ippicv_win\lib\ia32
D:\OpenCV-3.2.0\opencv\build\x86-static\3rdparty\lib\Release
Add OpenCV library
kernel32.libuser32.lib
gdi32.lib
winspool.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
comdlg32.lib
advapi32.lib
opencv_highgui320.lib
opencv_core320.lib
ippicvmt.lib
zlib.lib
opencv_imgproc320.lib
opencv_imgcodecs320.lib
IlmImf.lib
libjpeg.lib
libjasper.lib
libpng.lib
libtiff.lib
libwebp.lib
opencv_video320.lib
opencv_videoio320.lib
vfw32.lib
Modify project configuration
Compile and Run
[OpenCV] 自行編譯 library for Visual Studio 2015
OpenCV 3.2.0 的安裝版本只有 X64 的 DLL 版本. 如果需要的不是這個版本, 就要自行編議. 譬如說, 主程式用到的是 X86 的編譯設定, 就需要 X86 的 DLL 版本. 如果不想要 release 的時候, 還要附帶一堆 DLL, 或是程式裡面已經用到了 /MT 的編譯選項, 那麼就要自行編譯 static library 的版本.
OpenCV 3.2.0 的 source code, 需要用 CMake 來做 configuration, 然後才能在 Visual Studio 2015 中編譯.
Download OpenCV 3.2.0 win pack
1. 下載 win pack (opencv-3.2.0-vc14.exe) from opencv.org
2. 解壓縮到硬碟中的任意目錄 : 這裡解壓縮到 D:\OpenCV-3.2.0
Download CMake
1. 在 CMake 的網站下載安裝檔. Download Page, 他有 ZIP 版及 MSI 不同的安裝程式, 以及 32/64 的版本. 除了不要在 32 位元的系統上安裝 64 位元的版本外, 其他應該都沒有問題.
2. 安裝完之後, 會在程式列多一個 CMake 的目錄, 其中的 CMake( cmake-gui ) 就是稍後要來做 configuration 用的.
Configure build with CMake
1. 執行 cMake-gui
2. 設定 OpenCV 原始碼及目的碼的位置. source code 在解壓縮出來的目錄中, 目的碼最好另外指定. 以下指定為 build/x86-static, 名稱就是他的意思.
3. 按下 “configure” 開始設定, generator 選擇 VS 2015
4. 等待 configuration 結束
5. 清除選項中的 BUILD_SHARED_LIBS, 以編譯靜態連結版本
6. 按下 “generate” 開始產生 Visual Studio 2015 的專案檔案
7. 等待 …
用 Visual Studio 2015 編譯 OpenCV Library
1. 執行 VS2015, 並開啟 “OpenCV” solution file
2. Build Solution
這個 solution 中, 包含了 66 個專案, 所以要 build 一段時間, build 完會產生如下的檔案
2017年2月16日 星期四
OpenCV Mask (Filter) performance comparison
OpenCV 的內建 filter2D 函式, 實作了影像處理上常用的 Mask, 或是稱為 Filter, Convolution, 的操作. 通常這也是影像相關的演算法的骨幹, 也是最耗費時間的環節.
Mask 的運算時間, 和 Mask 的組成有絕對的關係, 以下套用不同的 Mask, 來觀察他運算時間上的差異.
比較 filter2D()以及自行撰寫的 C 函式
Index | Implement | ms |
C Function | *output++ = saturate_cast<uchar>(5*current[i] -current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]); | 64.909 |
filter2D | Mat kernel = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); filter2D( src, dst1, src.depth(), kernel ); | 3.030 |
不同 Mask 的時間比較
Index | Implement | ms |
1x1 | Mat kernel_1x1 = (Mat_<char>(1,1) << 1); | 1.134 |
3x3 | Mat kernel_3x3 = (Mat_<char>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); | 2.718 |
5x5 | Mat kernel_5x5 = (Mat_<char>(5,5) << 0,0,-1,0,0,0,0,-1,0,0,-1,-1,9,-1,-1,0,0,-1,0,0,0,0,-1,0,0); | 4.313 |
7x7-1 | Mat kernel_7x7 = (Mat_<char>(7,7) << 0,0,0,-1,0,0,0, 0,0,0,-1,0,0,0, 0,0,0,-1,0,0,0, -1,-1,-1,13,-1,-1,-1, 0,0,0,-1,0,0,0, 0,0,0,-1,0,0,0, 0,0,0,-1,0,0,0); | 6.170 |
7x7-2 | Mat kernel_7x7_2 = (Mat_<char>(7,7) << -4,-3,-2,-1,-2,-3,-4, -3,-3,-2,-1,-2,-3,-3, -2,-2,-2,-1,-2,-2,-2, -1,-1,-1,107,-1,-1,-1, -2,-2,-2,-1,-2,-2,-2, -3,-3,-2,-1,-2,-3,-3, -4,-3,-2,-1,-2,-3,-4); | 22.44 |
2017年2月15日 星期三
[OpenCV] LUT access time comparison
比較 OpenCV 做 Look Up Table 的效率.
OpenCV 提供了幾種作 Look Up Table 的動作的方法. 以下對這幾種方法做效率上的比較, 同時加上以 C 的 Pointer 的存取方式.
Index | Reference Code | ms |
C Pointer | for( int i = 0; i < scan_size; i ++ ) { * pDest = pTable[ * pSrc ]; pDest ++; pSrc ++; } | 4.98 |
C [] | for( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); for ( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; } } | 5.12 |
iterator | MatIterator_<Vec3b> it, end; for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; } | 170.45 |
Random Access | Mat_<Vec3b> _I = I; for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; | 291.56 |
LUT | LUT(I, lookUpTable, J); | 5.72 |
Note :
- C Pointer 的作法只是做為一個參考, 以 C 程式指令來說, 應該已經是最快的, 這裡主要是用來作為對比.
- C [] 所耗費的時間略多, 主要應該是用到索引定址的關係. 因為它要先做計數器累加.
- OpenCV 的 LUT() 函式耗費時間較多. 通用型的函式, 一般來說, 都會比特用型的函式, 來得慢一些, 這樣的時間, 是滿不錯的了.
- iterator 的存取方式的耗時, 非常的不好, 是 30~40 倍的慢. 顯然這種存取方式, 並不適合用來做 LookUpTable 這種對大量記憶體做簡單運算的動作. 它在存取每一個點的 overhead 太大, 需要做 iterator 前進到下一點的動作, 對每一點的存取也需要做多次的計數器及取址.
- Random Access, 用 Random Access 的方法, 來做 Sequential Access, 就好像拿拖把掃地, 這邊也是作為參考.