Перейти к содержимому
Compvision.ru
Argon

Рисование на изображении (установка ROI)

Recommended Posts

Все тот же синтаксис....

для простоты и удобства при ранесении ROI вызываю дополнительное окно:

void MouseDetected::on_pushButton_2_clicked()

{

    cv::namedWindow("ROI", 1);

    cv::imshow("ROI", frame);


    //вызываю обработчик нажатия книпки мыши frame беру как кадр из видео файла

    cv::setMouseCallback("ROI", myMouseCallback, (void*) frame);


}
пишу обработчик для функции myMouseCallback
void myMouseCallback( int event, int xA, int yA, int flags, void* param )

{

        IplImage* img = (IplImage*) param;

        cv::Mat matImg(img);


        switch( event ){

                case CV_EVENT_MOUSEMOVE:

                        break;


                case CV_EVENT_LBUTTONDOWN:


                        drawTarget(img, xA, yA, 10);

                        break;


                case CV_EVENT_LBUTTONUP:

                        break;

        }

}
и описываю drawTarget
void drawTarget(cv::Mat img, int xA, int yA, int radius)

{


        cv::circle(img,cv::Point(xA, yA),radius,cv::Scalar(250,0,0),1,8);

        cv::line(img, cv::Point(xA-radius/2, yA-radius/2), cv::Point(xA+radius/2, yA+radius/2),cv::Scalar(250,0,0),1,8);

        cv::line(img, cv::Point(xA-radius/2, yA+radius/2), cv::Point(xA+radius/2, yA-radius/2),cv::Scalar(250,0,0),1,8);

}

в итоге ругается на строку

cv::setMouseCallback("ROI", myMouseCallback, (void*) frame);

488: ошибка: cannot convert 'MouseDetected::myMouseCallback' from type 'void (MouseDetected::)/>()' to type 'cv::MouseCallback {aka void (*)(int, int, int, int, void*)}'

гугл особо ничем не помог. В чем может быть проблема?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Вынеси myMouseCallback из класса или сделай статической функцией.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо! Сделал статической и ошибка пропала, но появилась другая, на этой же стороке...

cv::setMouseCallback("ROI", myMouseCallback, (void*) frame);

ошибка: invalid cast from type 'cv::Mat' to type 'void*'

подскажите что с этим делать???

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Поставить (void*)&frame наверное?

И внутри myMouseCallback тогда делать сразу cv::Mat matImg(*(cv::Mat*)param).

Должно заработать, но подход всё равно кривенький.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо! заработало!

А что значит подход кривенький? Как это можно сделать лучше?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Классикой (с момента появления С++) считается делать каллбэк статической функцией класса (у тебя уже) и передавать в качестве параметра указатель на класс, то есть (void*)this. В этой функции кастовать param к указателю на тип своего класса и уже с ним работать.

Ещё раньше (в просто С без плюсов) использовался подобный подход, но без static и this.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

еще вопрос

решил попробовать дать пользователю выделять область ROI самому, но у меня не получается выделить область....

делаю сл. образом:

void drawTarget(cv::Mat img, int xA, int yA, cv::Rect poli1)

{

    cv::rectangle(img, cv::Point(poli1.x, poli1.y), cv::Point(xA, yA),cv::Scalar(250,0,0),1,8);

}


void MouseDetected::myMouseCallback( int event, int xA, int yA, int flags, void* param )

{


    cv::Mat matImg(*(cv::Mat*)param);

    cv::Rect pol1;


        switch( event ){


                case CV_EVENT_LBUTTONDOWN:

        {

                        pol1.width = xA;

                        pol1.height = yA;


                        cv::circle(matImg,cv::Point(xA, yA),1,cv::Scalar(250,0,0),3,8);

        }

                        break;


                case CV_EVENT_LBUTTONUP:


                        break;


                case (CV_EVENT_LBUTTONDOWN && CV_EVENT_MOUSEMOVE):


                        {

                             if ((pol1.x != NULL) || (pol1.y != NULL) )

                             {

                                   drawTarget(matImg, xA ,yA, pol1);

                             }

                        }

                        break;

        }

}

но ничего не происходит... ставится только точка нажатия курсора и все.... подскажите что не так???

ЗЫ: чет я совсем запутался с cv::Point и cv::Rect....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это не то, чего добиваетесь?

http://www.compvision.ru/forum/index.php?showtopic=1161

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

то, только я не совсем понимаю как это у Вас работает.

а точнее: как вы сохраняете по клику мыши координаты точки?

каким параметром передаете на рисование?

как делаете только одну прорисовку области до отжатия левой кнопки мыши?

и почему везде ссылки на класс annotation?

подробнее опишите процеесс сохранения ROI в переменную(cv::Rect)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Этот кусок кода переделан из кода для разметки точек ASM модели из книги mastering opencv (есть в списке книг по opencv), оттуда и класс annotation.

Точки сохраняются по нажатию кнопки ( CV_EVENT_LBUTTONDOWN ) в std::vector , при помощи push_back.

Экземпляр класса annotation объявлен глобально, поэтому его видно из функций обратного вызова (не очень то красиво, лучше сделать как Nuzhny советовал , но переделывать не хочу).

Этот класс содержит в себе чистое изображение, и изображение на котором будем рисовать, и которое будем показывать.

Перед тем, как что то рисовать всегда сохраняем истое изображение, чтобы им можно было стирать нарисованное ранее.

Функция обратного вызова работает во время "висения" окна на команде waitKey(0).

Точки там хранятся попарно, одна пара точек - один прямоугольник.

Кладете в cv::Rect первую точку в качестве координат, и разницу между точками в качестве размеров.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо!

Еще маленьки вопросик:

есть переменные в которых храню координады точек прямоугольника(левая верхняя, нижняя правая)

к примеру(int)

ixAUp = 100;

     iyAUp = 100;

     ixADown = 200;

     iyADown = 300;
а вот когда начинаю их записывать в спинбоксы, то тут хз что происходит: записывается только первая переменная в первый спинбокс... ...остальные игнорируются записываю так:
ui->spinXup->setValue(ixAUp);

        ui->spinYup->valueChanged(iyAUp);

        ui->spinXdown->setValue(ixADown);

        ui->spinYdown->setValue(iyADown);

еще нюанс: когда закоменчу первую строку заполнения спинбоксов, то будет заполнять только второй спинбокс....

помогите разобраться с бональным кодом....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

извините мой косяк: использовал setValue, а другой функцией касался valueChange .... ...дорогой же учитель опыт....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Еще вопрос:

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

накладываю так

cv::putText(matOriginal, "Object in ROI A: " + t_TimeObjA.toString() ,cv::Point(10,25),CV_FONT_HERSHEY_COMPLEX, 0.4f, cv::Scalar(255,255,255),1,CV_AA);
но если использую
QMessagebox::information(this, "1", t_TimeObjA.toString())

то выводит сообщение с временем как нужно (00:00:00)...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Выделите буфер, скопируйте в него t_TimeObjA.toString(),

и содержимое буфера выводите. Можно попробовать через sprintf.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Спасибо, но не получилось по вашему совету

делал так

QString text = t_TimeForEditA.toString();

                        const std::string textTime = text.toStdString();

                        cv::putText(matOriginal,"Object in ROI A: " + textTime ,cv::Point(10,25),CV_FONT_HERSHEY_COMPLEX, 0.4f, cv::Scalar(255,255,255),1,CV_AA);

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

но т.к. код тормозил выполнение программы пришлось его сократить


                        cv::putText(matOriginal,"Object in ROI A: " + t_TimeForEditA.toString().toStdString() ,cv::Point(10,25),CV_FONT_HERSHEY_COMPLEX, 0.4f, cv::Scalar(255,255,255),1,CV_AA);

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

cout << t_TimeForEditA.toString().toStdString();

корректный результат выводит?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×