Функция обратного вызова OpenCV Trackbar и неожиданные изменения состояния

0

Когда я запускаю эту программу и настраиваю несколько раз несколько ползунков, изображение становится другим, даже если оно находится в том же положении ползунка. Если вы попробуете этот код, переместите ползунок с минимального на максимальное положение назад и вперед несколько раз, и вы можете видеть небольшое изменение изображения каждый раз.

Я проследил точку, в которой это происходит с линией, выполняющей функцию добавления в моей функции onProgram6Trackbar1. Удаление его устраняет изменения между перемещениями слайдов. Почему это происходит?

#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 ()? Я нашел этот отчет об ошибке, который может иметь отношение к этому сообщению. code.opencv.org/issues/2658
  • 0
    или это, code.opencv.org/issues/1460
Показать ещё 2 комментария
Теги:
opencv

1 ответ

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 выполняется отлично.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню