2014-06-06 81 views
0

當我運行此程序並多次調整滑塊時,即使圖像位於同一滑塊位置,圖像也顯示爲不同。如果您嘗試使用此代碼,請將滑塊從最小位置移動到最大位置數次,每次您都可以看到圖像的輕微變化。OpenCV Trackbar回調函數和意外狀態更改

我已經追蹤了這種情況發生在我的onProgram6Trackbar1函數中運行add函數的那一行。刪除它可消除滑動移動之間的差異。這是爲什麼發生?

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream> 
#include <string> 

using namespace cv; 
using namespace std; 
#include <cmath> 

class ProgramData { 
    public: 
    ProgramData() { 
     k1=0; 
     k2=0; 
     k3=0; 
     k4=0; 
     k5=0; 
    } 
    int k1; 
    int k2; 
    int k3; 
    int k4; 
    int k5; 
    Mat * source_U8C3; 
    Mat * temp1_U8C3; 
    Mat * temp2_U8C3; 
    Mat * temp3_U8C1; 
    Mat * temp4_U8C1; 
    Mat * temp5_U8C1; 
    Mat * temp6_U8C1; 
    Mat * temp7_U8C1; 
    vector<Mat> tempv1_U8C1; 
    vector<Mat> tempv2_U8C1; 
    Mat * output_U8C1; 
    Mat * output_U8C3; 
    Mat * dim1by1; 
}; 

static void onProgram6Trackbar1(int v, void* vp) { 
     ProgramData * pd = (ProgramData *) vp; 
     *(pd->temp3_U8C1) = pd->tempv1_U8C1[2].clone(); 
     inRange(*(pd->temp3_U8C1), pd->k1, 255, *(pd->temp4_U8C1)); 
     bitwise_not(*(pd->temp4_U8C1), *(pd->temp5_U8C1)); 
     bitwise_and(*(pd->temp5_U8C1), *(pd->temp3_U8C1), *(pd->temp6_U8C1)); 
     bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1); 
     imshow("Glare Reduction 4", *(pd->temp7_U8C1)); 
} 

void program6(char * argv) { 
    ProgramData pd; 
    pd.k1 = 0; 
    Mat source = imread(argv, IMREAD_COLOR); // Read the file 
    pd.source_U8C3 = &source; 
    Size s(pd.source_U8C3->size().width/1.3, pd.source_U8C3->size().height/1.3); 
    resize(*(pd.source_U8C3), *(pd.source_U8C3), s, 0, 0, CV_INTER_AREA); 

    pd.output_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type()); 
    pd.output_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    //pd.temp1_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type()); 
    pd.temp2_U8C3 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,pd.source_U8C3->type()); 
    pd.temp3_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    pd.temp4_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    pd.temp5_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    pd.temp6_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    pd.temp7_U8C1 = new Mat(pd.source_U8C3->rows,pd.source_U8C3->cols,CV_8UC1); 
    pd.dim1by1 = new Mat(100,800,CV_8UC1); 
    cout << "source type = " << pd.source_U8C3->type() << endl; 

    if(! pd.source_U8C3->data) { cout << "Could not open image" << std::endl; return;} 
    cvtColor(*(pd.source_U8C3), *(pd.temp2_U8C3), CV_BGR2HSV); // original to hsv 
    split(*(pd.temp2_U8C3), pd.tempv1_U8C1); 

    namedWindow("Glare Reduction - Controls", WINDOW_AUTOSIZE); // Create a window for display. 
    onProgram6Trackbar1(0,&pd); 
    createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd); 
    imshow("Glare Reduction - Controls", *(pd.dim1by1)); // Show our image inside it. 

    waitKey(0); // Wait for a keystroke in the window 
} 

int main(int argc, char** argv) 
{ 
    program6("Blocks1.jpg"); 
} 

更新1:

新代碼貼在下面。我試着改變代碼以不使用任何Mat指針。仍然做同樣的事情。

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream> 
#include <string> 

using namespace cv; 
using namespace std; 
#include <cmath> 

class ProgramData { 
    public: 
    ProgramData() { 
     k1=0; 
    } 
    int k1; 
    Mat source_U8C3; 
    Mat temp1_U8C3; 
    Mat temp2_U8C3; 
    Mat temp3_U8C1; 
    Mat temp4_U8C1; 
    Mat temp5_U8C1; 
    Mat temp6_U8C1; 
    Mat temp7_U8C1; 
    vector<Mat> tempv1_U8C1; 
    vector<Mat> tempv2_U8C1; 
    Mat output_U8C1; 
    Mat output_U8C3; 
    Mat dim1by1; 
}; 

static void onProgram6Trackbar1(int v, void* vp) { 
     ProgramData * pd = (ProgramData *) vp; 
     pd->temp3_U8C1 = pd->tempv1_U8C1[2].clone(); 
     inRange(pd->temp3_U8C1, Scalar(pd->k1), Scalar(255), pd->temp4_U8C1); 
     bitwise_not(pd->temp4_U8C1, pd->temp5_U8C1);         // Note for monday, here does not work below works. Why? 
     bitwise_and(pd->temp5_U8C1, pd->temp3_U8C1, pd->temp6_U8C1); 
     bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1); 
     imshow("Glare Reduction 4", pd->temp7_U8C1); 
} 

int main(int argc, char** argv) { 
    ProgramData pd; 
    pd.k1 = 0; 
    pd.source_U8C3 = imread("Photo Examples/Blocks1.jpg", IMREAD_COLOR); // Read the file 
    Size s(pd.source_U8C3.size().width/1.3, pd.source_U8C3.size().height/1.3); 
    resize(pd.source_U8C3, pd.source_U8C3, s, 0, 0, CV_INTER_AREA); 
    pd.dim1by1.create(100,800,CV_8UC1); 
    cout << "source type = " << pd.source_U8C3.type() << endl; 
    if(! pd.source_U8C3.data) { cout << "Could not open image" << std::endl; return 0;} 
    cvtColor(pd.source_U8C3, pd.temp2_U8C3, CV_BGR2HSV); // original to hsv 
    split(pd.temp2_U8C3, pd.tempv1_U8C1); 
    namedWindow("Glare Reduction - Controls", WINDOW_AUTOSIZE); // Create a window for display. 
    onProgram6Trackbar1(0,&pd); 
    createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd); 
    imshow("Glare Reduction - Controls", pd.dim1by1); // Show our image inside it. 
    waitKey(0); // Wait for a keystroke in the window 
    return 0; 
} 

更新2:

我想我可能已經找到了問題的根源。當添加此行

static void onProgram6Trackbar1(int v, void* vp) { 
     ProgramData * pd = (ProgramData *) vp; 
     pd->temp3_U8C1 = pd->tempv1_U8C1[2].clone(); 
     inRange(pd->temp3_U8C1, Scalar(pd->k1), Scalar(255), pd->temp4_U8C1); 
     bitwise_not(pd->temp4_U8C1, pd->temp5_U8C1);         
     bitwise_and(pd->temp5_U8C1, pd->temp3_U8C1, pd->temp6_U8C1); 
     pd->temp7_U8C1 = pd->tempv1_U8C1[2].clone(); // <---- 
     bitwise_or(pd->temp6_U8C1, Scalar(pd->k1), pd->temp7_U8C1, pd->temp4_U8C1); 
     imshow("Glare Reduction 4", pd->temp7_U8C1); 
} 

to onProgram6Trackbar1它突然按預期工作。我想,因爲opencv 2自己的內存分配,我沒有必要初始化pd-> temp7_U8C1這是在調用bitwise_or作爲輸出矩陣。它幾乎就像pd-> temp7_U8C1中的底層內存指向的是屬於某個緩衝區的內存,該緩衝區用作主要(pd.tempv1_U8C1或pd.source_U8C3)中完成的圖像處理的輸出。我添加的這一行做了一些我沒有想到的事情。

所以我的新問題是爲什麼這條線修復它,以及底下發生了什麼。是否在文檔中使用未初始化的墊子行爲定義的結果?我的理解是,您不必初始化您用作輸出墊的矩陣的大小或類型。

+0

它可能是一個與Scalar()的行調用問題?我發現這個錯誤報告可能與這篇文章有關。 http://code.opencv.org/issues/2658 – user1505520

+0

或這個,http://code.opencv.org/issues/1460 – user1505520

+0

這可能會或可能不會涉及到你的問題,但你正在乞求使用' Mat *'指針無處不在。只需存儲'Mat'對象。 – Aurelius

回答

0

可能有點老了,反正:首先檢查稍微清潔的代碼。我刪除了冗餘的所有內容,並將跟蹤欄的實際功能發送給您的班級成員。這樣,您可以直接操作會員。

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream> 
using namespace cv; 
using namespace std; 

class ProgramData 
{ 
public: 
    ProgramData() 
    { 
     k1 = 0; 
    } 
    int k1; 
    Mat source_U8C3, 
     temp2_U8C3, temp4_U8C1, 
     temp5_U8C1, temp6_U8C1, 
     temp7_U8C1; 
    vector<Mat> tempv1_U8C1; 

    void reduce_glare(void) 
    { 
     // sets elements in temp4 to 255 if within range 
     inRange(tempv1_U8C1[2], Scalar(k1), Scalar(255), temp4_U8C1); 

     // bitwise_not(InputArray src, OutputArray dst) 
     bitwise_not(temp4_U8C1, temp5_U8C1); 

     // bitwise_and(InputArray src1, InputArray src2, OutputArray dst) 
     bitwise_and(temp5_U8C1, tempv1_U8C1[2], temp6_U8C1); 

     // watch out here: 
     temp7_U8C1 = Mat::ones(tempv1_U8C1[2].size(), CV_8UC1); 
     Mat x = Mat::ones(tempv1_U8C1[2].size(), CV_8UC1) * k1; 

     // bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask) 
     bitwise_or(temp6_U8C1, x, temp7_U8C1, temp4_U8C1); 
     cout << "source type = " << temp7_U8C1.type() << endl; 
     cout << "source channels = " << temp7_U8C1.channels() << endl; 
     cout << "source depth = " << temp7_U8C1.depth() << endl; 
    } 
}; 

void onProgram6Trackbar1(int v, void *vp) 
{ 
    ProgramData *pd = static_cast<ProgramData *>(vp); 
    (*pd).reduce_glare(); 
    imshow("Glare Reduction 4", pd->temp7_U8C1); 
} 

int main(int argc, char **argv) 
{ 
    ProgramData pd; 

    pd.source_U8C3 = imread("CutDat.jpeg", IMREAD_COLOR); 
    Size s(pd.source_U8C3.size().width/1.3, pd.source_U8C3.size().height/1.3); 
    resize(pd.source_U8C3, pd.source_U8C3, s, 0, 0, CV_INTER_AREA); 

    cout << "source type = " << pd.source_U8C3.type() << endl; 

    cvtColor(pd.source_U8C3, pd.temp2_U8C3, CV_BGR2HSV); 
    split(pd.temp2_U8C3, pd.tempv1_U8C1); 

    namedWindow("Glare Reduction - Controls", WINDOW_AUTOSIZE); 
    imshow("Glare Reduction - Controls", Mat(100, 800, CV_8UC1)); 

    createTrackbar("k1", "Glare Reduction - Controls", &(pd.k1), 255, &onProgram6Trackbar1, &pd); 

    waitKey(0); 
    return 0; 
} 

重要的是temp7_U8C1初始化的行,但不是與原始數據。你得到的結果仍然不是你想要的,但它強調了這個問題在bitwise_or的調用中。您在Scalar錯誤中的問題在此處不適用,因爲我已在代碼中顯示它。

該代碼在2.4.10和Ubuntu 2.4.8的Windows上測試,兩者都給出了相同的結果。在valgrind上測試代碼運行良好。