1. 程式人生 > >OpenCV 系列 --- 互動(一)滑動條

OpenCV 系列 --- 互動(一)滑動條

對影象處理來說,很多時候需要與使用者進行互動,最典型的應用有兩種:

(1) 在演算法設計時,要根據某一引數的不同取值來進行相應的計算;

(2) 互動式分割演算法

其中,對第1種情況而言,OpenCV提供了滑動條,可以靈活地設定引數值來進行相應的處理。而對第2種情況而言,則提供了滑鼠互動,首先我們介紹關於滑動條的知識點,下文將會給出滑鼠的相關知識點。

  1. 為了更好地說明滑動條的應用,我採用Canny邊緣檢測演算法來進行演示,其呼叫方式為:
void Canny(InputArray image, OutputArray edges, double threshold1, double
threshold2, int apertureSize=3, bool L2gradient=false )

其中,image代表輸入影象,這裡為單通道影象;edges為單通道的邊緣圖;threshold1與threshold2是Canny邊緣檢測演算法的兩個閾值;apertureSize與L2gradient有預設值,因此在這篇文章裡不進行解釋,感興趣的可以去官方網站查詢。

  1. 對滑動條來說,其函式呼叫方式為:
int createTrackbar(const string& trackbarname, const string& winname, int* value
, int count, TrackbarCallback onChange=0, void* userdata=0)

關於這幾個引數的解釋如下:
* trackbarname: 滾動條的名字,通常指滾動條前的一串字元
* winname:滾動條所在視窗的名字,這個其實是定義了滾動條所依賴的主視窗的名字
* value:滑塊的位置,在建立時,此值即為初始值
* count:滑塊的最大值,對滑塊來說,最小值始終為0
* TrackbarCallback:這個是最核心的,指向回撥函式的指標,當滑塊位置改變時,就會呼叫指向的函式,從而達到互動的目的
* userdata:預設值為0。此值是使用者傳給回撥函式的值,用來進行相應的處理。如果value的值設定為全域性變數,則滑動塊的值可以由value來進行控制,可以不設定userdata

  1. 測試用的完整程式碼如下:
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace cv;
using namespace std;

Mat imgSrc;//輸入影象,彩色
Mat imgEdge;//邊緣影象
Mat imgGray;//輸入影象,灰度影象

const int g_nMaxThresh = 255;
int g_nThresh_low;
int g_nThresh_high;

void on_Trackbar(int,void*);

int main()
{
    imgSrc = imread("running.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);

    cvtColor(imgSrc, imgGray, CV_RGB2GRAY);//彩色影象轉換為灰度圖

    g_nThresh_low  = 0;//初始化低閾值值0
    g_nThresh_high = 0;//初始化高閾值為0

    namedWindow("Edge Detection", WINDOW_AUTOSIZE);//生成主視窗,用來容納滾動條與影象
    imshow("Edge Detection", imgGray);

//建立一個滑動條,名字為Low:255,主視窗為Edge Detection,最大值為255,value為g_nThresh_low,回撥函式為on_trackbar
    createTrackbar("Low: 255", "Edge Detection", &g_nThresh_low, 255, on_Trackbar);

//建立一個滑動條,名字為High: 255,主視窗為Edge Detection,最大值為255,value為g_nThresh_high,回撥函式為on_trackbar  
    createTrackbar("High: 255", "Edge Detection", &g_nThresh_high, 255, on_Trackbar);

    waitKey(0);
    return 0;
}
//回撥函式
void on_Trackbar(int, void*)
{
    cout << "Threshold value: " <<endl;
    cout << "High: " << g_nThresh_high << endl;
    cout << "Low: " << g_nThresh_low << endl << endl;

//呼叫Canny邊緣檢測演算法,imgGray為輸入影象,imgEdge為邊緣影象,g_nThresh_low與g_nThresh_high是兩個閾值
    Canny(imgGray, imgEdge, g_nThresh_low, g_nThresh_high);

    imshow("Edge Detection", imgEdge);
}
  1. 程式執行結果
    拖動滑動條的位置,在閾值改變時,程式可以實時地得到邊緣檢測的效果

    • 程式的初始視窗如下:

    • 拖動滑動條,改變高低閾值,低閾值設定為16,高閾值設定為38,結果如下:

    • 拖動滑動條,改變高低閾值,低閾值設定為194,高閾值設定為208,結果如下:
      這裡寫圖片描述

可以看出,不同的高低閾值可以得到不同的邊緣檢測效果。對我來說,現在在採用邊緣檢測結果時,基本不會用這些基本的邊緣檢測演算法,我會用一些比較近代的邊緣檢測演算法,比如Structured forest等演算法,效果很不錯。