Assume I have two windows: Blurring window and Cannying window.
Blurring window has one trackbar to change the kernel size.
Cannying window depends on the blurred Mat object.
If I change the trackbar on the Blurring window, the blurred Mat object changes, as a result it must also change the image displayed on Cannying window.
Is it possible to orchestrate these two windows?
import cv2 as cv
blur_radius = 0
#blur_radius = cv.getTrackbarPos("blur_strength", "blur")
# then you won't need the global `blur_radius` and assignment in the callback below
blur = ... do blur using blur_radius ...
... do canny ...
... imshow the canny result ...
# absolutely NO waitKey here
def trackbar_callback(pos): # and maybe userdata, see docs
# using getTrackbarPos (above), these two lines need to be removed:
blur_radius = pos
if __name__ == '__main__':
cv.createTrackbar("blur_strength", "blur", ..., onChange=trackbar_callback)
draw() # first call to show *something*
# main loop does nothing but waitKey
# waitKey does all event and callback processing
key = cv.waitKey(1000)
if key == -1:
continue # it was a timeout
elif key in (13, 27): # ENTER, ESC
print("key code", key)
for this simple case, you could pass the trackbar position into the draw() call… but that’s not extensible.
when you add more control elements, the state of those values needs to be kept somewhere. if you don’t, you would have to query the positions of all trackbars in the draw() call (see the “option”).
I am not familiar with python but c++. Now I am trying to understand this code.
Thank you very much.
By the way, please increase the width of the HTML element containing this posts. The code box is too narrow, as a result I have to scroll horizontally. It is unpleasant.
Attempting to enlarge the width with CTRL+Mouse Scroll does not help because the font size becomes too gigantic.
Only for sharing if you want to see the code in C++.
using namespace std;
using namespace cv;
const string wndInput = "Input";
const string wndGrayed = "Grayed";
const string wndBlurred = "Blurred";
const string wndCannied = "Cannied";
const string tbKSize = "KSize";
const string tbThd1 = "Threshold1";
const string tbThd2 = "Threshold2";
const int KSIZE_MAX = 200;
const int THD1_MAX = 200;
const int THD2_MAX = 200;
const string path = "../resources/test.png";
Mat input = imread(path);
int kSize = getTrackbarPos(tbKSize, wndBlurred);
int thd1 = getTrackbarPos(tbThd1, wndCannied);
int thd2 = getTrackbarPos(tbThd2, wndCannied);
if (kSize % 2 != 0)
// size must be odd integers.
GaussianBlur(input, blurred, cv::Size(kSize, kSize), 3, 0);
Canny(blurred, cannied, thd1, thd2);
void onThd1(int, void *)
void onThd2(int, void *)
void onKSize(int, void *)
cvtColor(input, grayed, cv::COLOR_BGR2GRAY);
int kSize = 71;
int thd1 = 50;
int thd2 = 100;
createTrackbar(tbKSize, wndBlurred, &kSize, KSIZE_MAX, onKSize);
createTrackbar(tbThd1, wndCannied, &thd1, THD1_MAX, onThd1);
createTrackbar(tbThd2, wndCannied, &thd2, THD2_MAX, onThd2);
cout << "===== END =====" << endl;