OpenCV Trackbar回调函数和意外状态更改

时间:2014-06-06 19:29:19

标签: c++ opencv

当我运行此程序并多次调整滑块时,即使图像处于相同的滑块位置,图像也会显示不同。如果您尝试此代码,请将滑块从最小位置前后移动几次,每次都可以看到图像略有改动。

我已经跟踪了在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);
}

到onProgram6Trackbar1它突然按预期工作。我认为,由于opencv 2进行了自己的内存分配,我没有必要初始化pd-&gt; temp7_U8C1,它在调用bitwise_or时用作输出矩阵。它几乎就像pd-&gt; temp7_U8C1中的底层内存指向属于其中一个缓冲区的内存,该缓冲区用作main(pd.tempv1_U8C1或pd.source_U8C3)中完成的图像处理的输出。我添加的这一行都做了一些我没有想过的事情。

所以我的新问题是为什么这行修复它以及下面发生了什么。使用文档中某处定义的未初始化的mat行为的结果是什么?我的理解是,您不必初始化您用作输出垫的矩阵的大小或类型。

1 个答案:

答案 0 :(得分: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错误的问题不适用于我在代码中显示的内容。

代码在Windows上使用2.4.10和Ubuntu 2.4.8进行测试,两者都给出了相同的结果。在valgrind上测试代码运行正常。