AI人工智能与数学之美

opencv C++ trackbar回调函数的参数传递

2020-12-03  本文已影响0人  1037号森林里一段干木头

简介:

opencv的highgui里有一个trackbar控件,可以动态改变参数,让图片实现实时变化。opencv官网的例子并没有用参数传递,而是用的是全局变量,这样会导致程序结构混乱,所以研究了下变成函数参数传递的方式。

    • 创建trackbar控件的函数原型
int cv::createTrackbar  (   
const String &  trackbarname,
const String &  winname,
int *   value,
int     count,
TrackbarCallback    onChange = 0,
void *  userdata = 0 
)   

参数详解:

    • trackbar回调函数原型
typedef void(* cv::TrackbarCallback) (int pos, void *userdata)

参数详解:

    • 实例
      写一个阈值分割的小程序,滑动条控制分割阈值,参数传递时用结构体。
      完整代码如下:
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
struct mydata{
    cv::Mat img;//原图
    cv::Mat dst;//阈值分割后的图
    int th ;//阈值
};

void thresh_callback(int pos, void *p)
{
    mydata cfg = *(mydata *)p;//
    cv::threshold(cfg.img,cfg.dst,pos,255,cv::THRESH_TOZERO);
    cv::namedWindow("winname",0);
    cv::imshow("winname",cfg.dst);
}

int main()
{
    mydata cfg;
    std::string img_path = "C:\\Users\\bxzyz\\Desktop\\book\\opencv-cookbook\\images\\church01.jpg";
    cv::Mat img  = cv::imread(img_path);
    cv::Mat dst = img.clone();
    cfg.img = img;
    cfg.dst = dst;
    //cfg.ksize = cv::Size(5,5);
    int th = 127;//初始默认值
    int th_max = 255;
    
    while (1)
    {
        cv::createTrackbar("th", "winname", &th, th_max, thresh_callback, (void*)(&cfg));
        thresh_callback(th,&cfg);
        //按Esc键退出程序
        if (cv::waitKey(3)==27)
        {
            break;
        }
    }
    cv::destroyAllWindows();
}

核心在mydata cfg = *(mydata *)p;
把main函数里的mydata 的实例cfg的地址传递给void *p指针,然后把P强制类型转换,变成我们定义的结构体的类型。用这种方法就可以传递任何我们想要的数据了。

补充:

三个通道分开做阈值分割再合并的
效果


image.png

代码:


#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
struct mydata{
    cv::Mat img;
    cv::Mat dst;
    int th ;
    int thr;
    int thg;
    int thb;
    
};
// void thresh_callback(int pos, void *p)
// {
//  mydata cfg = *(mydata *)p;
//  cv::threshold(cfg.img,cfg.dst,pos,255,cv::THRESH_TOZERO);
//  cv::namedWindow("winname",0);
//  cv::imshow("winname",cfg.dst);
    
// }

void thresh_callback_r(int posr, void *p)
{
    mydata cfg = *(mydata *)p;
    cfg.thr = posr;
    std::vector<cv::Mat> channels(3);
    cv::split(cfg.img, channels);
    cv::threshold(channels[0],channels[0],cfg.thb,255,cv::THRESH_TOZERO);
    cv::threshold(channels[1],channels[1],cfg.thg,255,cv::THRESH_TOZERO);
    cv::threshold(channels[2],channels[2],cfg.thr,255,cv::THRESH_TOZERO);
    cv::merge(channels, cfg.dst);
    cv::namedWindow("winname",0);
    cv::imshow("winname", cfg.dst);
}

void thresh_callback_g(int posg, void *p)
{
    mydata cfg = *(mydata *)p;
    cfg.thg = posg;
    std::vector<cv::Mat> channels(3);
    cv::split(cfg.img, channels);
    cv::threshold(channels[0],channels[0],cfg.thb,255,cv::THRESH_TOZERO);
    cv::threshold(channels[1],channels[1],cfg.thg,255,cv::THRESH_TOZERO);
    cv::threshold(channels[2],channels[2],cfg.thr,255,cv::THRESH_TOZERO);
    cv::merge(channels, cfg.dst);
    cv::namedWindow("winname",0);
    cv::imshow("winname", cfg.dst);
}

void thresh_callback_b(int posb, void *p)
{
    mydata cfg = *(mydata *)p;
    cfg.thb = posb;
    std::vector<cv::Mat> channels(3);
    cv::split(cfg.img, channels);
    cv::threshold(channels[0],channels[0],cfg.thb,255,cv::THRESH_TOZERO);
    cv::threshold(channels[1],channels[1],cfg.thg,255,cv::THRESH_TOZERO);
    cv::threshold(channels[2],channels[2],cfg.thr,255,cv::THRESH_TOZERO);
    cv::merge(channels, cfg.dst);
    cv::namedWindow("winname",0);
    cv::imshow("winname", cfg.dst);
}

int main()
{
    mydata cfg;
    std::string img_path = "C:\\Users\\bxzyz\\Desktop\\book\\opencv-cookbook\\images\\church01.jpg";
    cv::Mat img  = cv::imread(img_path);
    cv::Mat dst = img.clone();
    cfg.img = img;
    cfg.dst = dst;
    //cfg.ksize = cv::Size(5,5);
    int th = 127;//初始默认值
    cfg.thr=0;
    cfg.thg=0;
    cfg.thb=0;
    int th_max = 255;
    
    while (1)
    {
        cv::createTrackbar("thr", "winname", &cfg.thr, th_max, thresh_callback_r, (void*)(&cfg));
        thresh_callback_r(cfg.thr,&cfg);

        cv::createTrackbar("thg", "winname", &cfg.thg, th_max, thresh_callback_g, (void*)(&cfg));
        thresh_callback_g(cfg.thg,&cfg);

        cv::createTrackbar("thb", "winname", &cfg.thb, th_max, thresh_callback_b, (void*)(&cfg));
        thresh_callback_b(cfg.thb,&cfg);
        
        if (cv::waitKey(1)==27)
        {
            break;
        }
    }
    
    cv::destroyAllWindows();
}



上一篇下一篇

猜你喜欢

热点阅读