[opencv][cpp] 多窗口多滑动条案例
文章目录
1. 两窗口多滑动条
1. 需求
创建两个 cv 窗口用来模拟处理图像 do_thresh,do_other,
窗口 do_thresh 包含两个滑动条 T_ty(0-3),T_th(0-255),
窗口 do_other 包含三个滑动条 T_th1(0-3),T_th2(0-100),T_th3(0-255)。
2. 完整代码
//
// Created by jacob on 12/29/20.
//
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
using namespace std;
namespace cvlog = cv::utils::logging;
/***-------------------- global variable --------------------***/
cv::Mat src, gray, binary;
double bin_thresh = 0;
int bin_type = 0;
struct BinData {
int sliderID;
std::string sliderName;
int th;
int ty;
};
int oth_Th1 = 0;
int oth_th2 = 0;
int oth_th3 = 0;
struct OtherData {
int sliderID;
std::string sliderName;
int th1;
int th2;
int th3;
};
/***-------------------- callback --------------------***/
void onThresholdBar(int sliderVal, void *userdata) {
const auto &slider = *static_cast<BinData *>(userdata);
auto sliderId = slider.sliderID;
auto sliderName = slider.sliderName;
int type;
double thresh;
if (sliderId == 0) {
CV_LOG_INFO(NULL, "sliderName: " << sliderName << ", value: " << sliderVal)
// if(sliderVal == 0){
//
// }else if(sliderVal == 1){
//
// }else if(sliderVal == 2){
//
// }else if(sliderVal == 3){
//
// }
} else if (sliderId == 1) {
CV_LOG_INFO(NULL, "sliderName: " << sliderName << ", value: " << sliderVal)
} else {
CV_LOG_INFO(NULL, "ERROR")
}
// do processing
CV_LOG_INFO(NULL, "bin_thresh: " << bin_thresh << ", bin_type: " << bin_type)
cv::threshold(gray, binary, thresh, 255, type);
}
void onOtherBar(int sliderVal, void *userdata) {
const auto &slider = *static_cast<BinData *>(userdata);
auto sliderId = slider.sliderID;
auto sliderName = slider.sliderName;
int type;
double thresh;
if (sliderId == 0) {
CV_LOG_INFO(NULL, "sliderName: " << sliderName << ", value: " << sliderVal)
} else if (sliderId == 1) {
CV_LOG_INFO(NULL, "sliderName: " << sliderName << ", value: " << sliderVal)
} else if (sliderId == 2) {
CV_LOG_INFO(NULL, "sliderName: " << sliderName << ", value: " << sliderVal)
} else {
CV_LOG_INFO(NULL, "ERROR")
}
// do processing
}
/***-------------------- entry --------------------***/
int main(int argc, char **argv) {
// setting up cv log
cvlog::setLogLevel(cvlog::LOG_LEVEL_INFO);
string filename = "../img/engline.jpg";
src = cv::imread(filename, cv::IMREAD_COLOR);
cv::imshow("src", src);
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
cv::imshow("gray", gray);
// image processing 1.
cv::namedWindow("do_thresh", cv::WINDOW_AUTOSIZE);
BinData bType{0, "type", 0, 0};
cv::createTrackbar("T_ty", "do_thresh", &bType.ty, 3, onThresholdBar, &bType);
BinData bThresh{1, "thresh", 0, 0};
cv::createTrackbar("T_th", "do_thresh", &bType.th, 255, onThresholdBar, &bThresh);
// image processing 2.
cv::namedWindow("do_other", cv::WINDOW_AUTOSIZE);
OtherData oThresh1{0, "th1", 0, 0, 0};
cv::createTrackbar("T_th1", "do_other", &oThresh1.th1, 3, onOtherBar, &oThresh1);
OtherData oThresh2{1, "th2", 0, 0, 0};
cv::createTrackbar("T_th2", "do_other", &oThresh2.th2, 100, onOtherBar, &oThresh2);
OtherData oThresh3{2, "th3", 0, 0, 0};
cv::createTrackbar("T_th3", "do_other", &oThresh3.th3, 100, onOtherBar, &oThresh2);
// pending main
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
3. 演示
2. 从滑动条回调函数中提取参数
1. 需求
在主函数中得到窗口滑动条位置数据
2. 完整代码
//
// Created by jacob on 12/29/20.
//
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
using namespace std;
namespace cvlog = cv::utils::logging;
/***-------------------- global variable --------------------***/
cv::Mat src, gray, binary;
int bin_type = 0;
double bin_thresh = 0;
struct BinData {
int sliderID;
std::string sliderName;
int th;
int ty;
};
/***-------------------- callback --------------------***/
void onThresholdBar(int sliderVal, void *userdata) {
const auto &slider = *static_cast<BinData *>(userdata);
auto sliderId = slider.sliderID;
auto sliderName = slider.sliderName;
if (sliderId == 0) { // type
// CV_LOG_INFO(CB, "sliderName: " << sliderName << ", value: " << sliderVal)
if (sliderVal == 0) {
bin_type = cv::THRESH_BINARY;
} else if (sliderVal == 1) {
bin_type = cv::THRESH_BINARY | cv::THRESH_TRIANGLE;
} else if (sliderVal == 2) {
bin_type = cv::THRESH_BINARY_INV;
} else if (sliderVal == 3) {
bin_type = cv::THRESH_BINARY_INV | cv::THRESH_TRIANGLE;
}
} else if (sliderId == 1) { // thresh
// CV_LOG_INFO(CB, "sliderName: " << sliderName << ", value: " << sliderVal)
bin_thresh = double(sliderVal);
} else {
CV_LOG_INFO(CB, "ERROR")
}
// do processing
CV_LOG_INFO(CB, "bin_thresh: " << bin_thresh << ", bin_type: " << bin_type)
cv::threshold(gray, binary, bin_thresh, 255, bin_type);
cv::imshow("do_thresh", binary);
}
/*
void print_type(){
CV_LOG_INFO(TYPE, "b_:" << cv::THRESH_BINARY) // 0
CV_LOG_INFO(TYPE, "b_t:" << (cv::THRESH_BINARY | cv::THRESH_TRIANGLE)) // 16
CV_LOG_INFO(TYPE, "bi_:" << cv::THRESH_BINARY_INV) // 1
CV_LOG_INFO(TYPE, "bi_t:" << (cv::THRESH_BINARY_INV | cv::THRESH_TRIANGLE)) // 17
}
*/
/***-------------------- entry --------------------***/
int main(int argc, char **argv) {
// setting up cv log
cvlog::setLogLevel(cvlog::LOG_LEVEL_INFO);
string filename = "../img/engline.jpg";
src = cv::imread(filename, cv::IMREAD_COLOR);
cv::imshow("src", src);
cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
cv::imshow("gray", gray);
// image processing 1.
cv::namedWindow("do_thresh", cv::WINDOW_AUTOSIZE);
BinData btData_type{0, "type", 0};
cv::createTrackbar("T_ty", "do_thresh", &btData_type.ty, 3, onThresholdBar, &btData_type);
BinData btData_thresh{1, "thresh", 0};
cv::createTrackbar("T_th", "do_thresh", &btData_thresh.th, 255, onThresholdBar, &btData_thresh);
onThresholdBar(0, &btData_type); // init once is enough
while (true) {
int key = cv::waitKey(2);
if (key == 27) {
break;
}
int ty = cv::getTrackbarPos("T_ty", "do_thresh");
int th = cv::getTrackbarPos("T_th", "do_thresh");
CV_LOG_INFO(WHILE, "T_ty: " << ty << ", T_th: " << th)
cv::imshow("binary_in_while", binary);
}
// pending main
cv::destroyAllWindows();
return 0;
}
3. 演示
&& 参考
链接:C++ 结构体初始化与赋值
链接:Callback机制
链接:Trackbar as the Color Palette
&& 问题解决
[待解决][部分解决,章节2] 如何获取滑动条回调函数中的数据?
- 使用全局变量?
- 使用 cv api?