網頁

2017年5月16日 星期二

[OpenCV] 3.2.0 實裝心得


OpenCV 3.2.0 已經在 2016/12/23 公開發行. 除了一些問題的修正外, 這一個版本的 Windows 版本是在 VC14, 也就是 Visual Studio 2015. 剛好接下來的工作也議定在 Visual Studio 2015 Community 上開發, 於是就選定用這個版本. 這個版本的使用上, 遇到的一些問題, 做個紀錄.

下載 :

直接在 OpenCV 的下載網頁下載 OpenCV download, 如果是在 Windows, 建議直接使用 Win pack 這個選項, 除了已經 build 好的 library, source code 也已經包含在裡面. 下載的檔名會是像 opencv-3.2.0-vc14.exe 這個樣子.

安裝 (解壓縮) :

下載下來的的 exe 是壓縮檔, 隨便解到那個目錄都可以. 這樣應該不算是安裝吧.

內容 :

3.2.0 的 Win pack 有 java 和 python 以及 VC 的版本, 除了 VC 以外, 都有 X86/X64 的版本, VC 則只有 X64 的版本. 如果要 X86 的版本, 就需要自己 build. 我需要的不只是 X86, 還要 static library 的版本, 所以需要自己 build.

2017年4月10日 星期一

[VideoInput] Download


Download VideoInput Libray from GitHub

https://github.com/ofTheo/videoInput to D://VideoInput
Extract
image

Synchronize project setting

image
image

Modification for Visual Studio 2015

VideoInput.cpp Line 821 as
        char * name =  (char*) videoInput::getDeviceName(i);

2017年4月9日 星期日

[OpenCV] Using OpenCV static library in MFC application


Create MFC Application

image

Add Picture Control

image

Add Initial codes in OnInitDialog

// TODO:  Add extra initialization here
CRect 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

image
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
Character Set –> Use Multi-Byte Character Set
/Configuration Properties/C/C++/Code Generation
Runtime Library –> Multi-thread (/MT)
Security Check –> Disable Security Check (/GS-)
/Configuration Properties/VC++ Directories
Include Directories: D:\OpenCV-3.2.0\opencv\build\include
Library Directires
image
/Configuration Properties/Linker/Input
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

image

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

Add OpenCV library path

D:\OpenCV-3.2.0\opencv\build\x86-static\lib\Release
D:\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.lib
user32.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

image
image
image

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.0image

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, 名稱就是他的意思.
image
3. 按下 “configure” 開始設定, generator 選擇 VS 2015
image
4. 等待 configuration 結束
5. 清除選項中的 BUILD_SHARED_LIBS, 以編譯靜態連結版本
image

6. 按下 “generate” 開始產生 Visual Studio 2015 的專案檔案
7. 等待 …
image

用 Visual Studio 2015 編譯 OpenCV Library

1. 執行 VS2015, 並開啟  “OpenCV” solution file
image
2. Build Solution

這個 solution 中, 包含了 66 個專案, 所以要 build 一段時間, build 完會產生如下的檔案

image

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
以 C 的實作來說, 差不多就是以上所列出來的程度. OpenCV 可以做到將近 20 倍的速度, 應該是用了一些硬體加速的方法.
不同 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
隨著 Mask 的 size 變大, 所耗費時間也跟著增加, 有趣的是 Mask 的內容也有很大的影響, 可見 OpenCV 會對於 零項作刪去的最佳化. 

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 :
  1. C Pointer 的作法只是做為一個參考, 以 C 程式指令來說, 應該已經是最快的, 這裡主要是用來作為對比.
  2. C [] 所耗費的時間略多, 主要應該是用到索引定址的關係. 因為它要先做計數器累加.
  3. OpenCV 的 LUT() 函式耗費時間較多. 通用型的函式, 一般來說, 都會比特用型的函式, 來得慢一些, 這樣的時間, 是滿不錯的了.
  4. iterator 的存取方式的耗時, 非常的不好, 是 30~40 倍的慢. 顯然這種存取方式, 並不適合用來做 LookUpTable 這種對大量記憶體做簡單運算的動作. 它在存取每一個點的 overhead 太大, 需要做 iterator 前進到下一點的動作, 對每一點的存取也需要做多次的計數器及取址.
  5. Random Access, 用 Random Access 的方法, 來做 Sequential Access, 就好像拿拖把掃地, 這邊也是作為參考.