python - cv2.imshow() 在自定义函数中不起作用

标签 python function opencv imshow

OpenCV imshow 函数似乎可以在函数外运行,但不能在函数内运行(我认为答案不是 waitKey())。为什么会发生这种情况,我该如何解决?

我正在学习 2D Gabor 小波。为了进行实验和观察,我首先创建了一个内核可视化工具。这是一个很好的、令人愉快的 javascript 代码,它向我展示了我正在创建的内核。如果您看一下,我将不胜感激:http://alpersunter.github.io/Gabor2D/

这显然没有告诉我应用内核后生成的图像的样子。因此,我安装了 OpenCV (4.1.0) 并在 python 上编写了一个程序(3.6.7 安装在 Ubuntu 18.04 上),据说它应该以与我的内核可视化器类似但更令人印象深刻的方式运行。它不仅要实时计算内核,还要对原始图像及其灰度对应物应用过滤器,最后显示它们。

我正在使用 cv2.createTrackbar() 创建 slider ,在任何参数更改后,轨迹栏调用“myValueChanged(newVal)”函数。该函数然后使用更新的参数计算新内核,最后重新绘制新图像(这是函数 cv2.filter2D(src, -1, kernel) 的返回值)。

现在,如果我在 valueChanged() 函数中调用 imshow() ,一切正常。但是,如果我将内核计算、内核应用程序和 cv2.imshow(result) 封装在另一个我称为“redraw()”的函数中,imshow 将无法工作。

这是我的代码示例:

import cv2
import numpy as np

messi_0_window = "Messi0" # original image
cv2.namedWindow(messi_0_window, cv2.WINDOW_NORMAL)
messi_grey_window = "Messigray" # grayscale of origial
cv2.namedWindow(messi_grey_window, cv2.WINDOW_NORMAL)
messi_1_window = "Messi1" # this will be the result of kernel convolution of rgb messi
cv2.namedWindow(messi_1_window, cv2.WINDOW_NORMAL)
messi_2_window = "Messi2" # and this will be the kernel conv. of grayscale messi
cv2.namedWindow(messi_2_window, cv2.WINDOW_NORMAL)
messi_0 = cv2.imread("messi.jpg")
messi_grey = cv2.cvtColor(messi_0, cv2.COLOR_BGR2GRAY)

kernelSize = (21, 21)
sigma = 10
theta = 0
psi = 0
lambd = 10

def thetaChanged(degrees):
    theta = (degrees/180)*np.pi
    print("I have got a call")
    kernel = cv2.getGaborKernel(kernelSize, sigma, theta, lambd, 1, psi)
    messi_1 = cv2.filter2D(messi_0, -1, kernel)
    messi_2 = cv2.filter2D(messi_grey, -1, kernel)
    cv2.imshow(messi_1_window, messi_1)
    cv2.imshow(messi_2_window, messi_2)

def psiChanged(degrees):
    psi = (degrees/180)*np.pi
    redraw()
    cv2.waitKey(1) # removing this line doesn't help

def redraw():
    print("I have got a call") # This is printed always when I move the slider, independent of whether new image is drawn or not

    kernel = cv2.getGaborKernel(kernelSize, sigma, theta, lambd, 1, psi)
    messi_1 = cv2.filter2D(messi_0, -1, kernel)
    messi_2 = cv2.filter2D(messi_grey, -1, kernel)
    cv2.imshow(messi_1_window, messi_1)
    cv2.imshow(messi_2_window, messi_2)


cv2.createTrackbar("Theta", messi_0_window, 0, 180, thetaChanged)
cv2.createTrackbar("Psi", messi_0_window, 0, 180, psiChanged)

cv2.imshow(messi_0_window, messi_0)
cv2.imshow(messi_grey_window, messi_grey)

cv2.waitKey()
print("Key is now pressed!")

当我移动 theta slider 时,屏幕上会绘制新图像。一切正常。但是,如果我移动 psi slider ,它只会绘制一次,然后停止绘制新图像。有趣的是,如果我再次移动 theta 并显示另一幅图像,psi slider 只会再工作一次然后再次停止。然后滑动 theta,psi 再次变为事件状态,但仅适用于一张图像。

我不知道如何解决这个问题,或者这是一个与 opencv 相关的问题。也许是因为我的 python 不好。不管怎样,我希望你能教我一些新东西。非常感谢教给我的任何新知识。

最佳答案

代码中的错误,psi 被视为 psiChanged 方法中的局部变量。您需要做的就是明确声明 psi 是该方法中的全局变量。对您的代码布局进行一些重构肯定会有所帮助。这是最终的工作脚本:

import cv2
import numpy as np

messi_0_window = "Messi0" # original image
cv2.namedWindow(messi_0_window, cv2.WINDOW_NORMAL)
messi_grey_window = "Messigray" # grayscale of origial
cv2.namedWindow(messi_grey_window, cv2.WINDOW_NORMAL)
messi_1_window = "Messi1" # this will be the result of kernel convolution of rgb messi
cv2.namedWindow(messi_1_window, cv2.WINDOW_NORMAL)
messi_2_window = "Messi2" # and this will be the kernel conv. of grayscale messi
cv2.namedWindow(messi_2_window, cv2.WINDOW_NORMAL)
messi_0 = cv2.imread("messi.jpg")
messi_grey = cv2.cvtColor(messi_0, cv2.COLOR_BGR2GRAY)

kernelSize = (21, 21)
sigma = 10
theta = 0
psi = 0
lambd = 10

def thetaChanged(degrees):
    global theta
    theta = (degrees/180)*np.pi # Changes the global `theta`
    print("Theta changed - {}".format(theta))
    redraw() # Removed the duplicate code and replaced it with `redraw()` method

def psiChanged(degrees):
    global psi
    psi = (degrees/180)*np.pi # Changes the global `psi`
    print("Psi changed - {}".format(psi))
    redraw()

def redraw():
    global kernelSize, sigma, theta, lambd, psi
    print("I have got a call - {}".format(psi)) # This is printed always when I move the slider, independent of whether new image is drawn or not

    kernel = cv2.getGaborKernel(kernelSize, sigma, theta, lambd, 1, psi)
    messi_1 = cv2.filter2D(messi_0, -1, kernel)
    messi_2 = cv2.filter2D(messi_grey, -1, kernel)
    cv2.imshow(messi_1_window, messi_1)
    cv2.imshow(messi_2_window, messi_2)


cv2.createTrackbar("Theta", messi_0_window, 0, 180, thetaChanged)
cv2.createTrackbar("Psi", messi_0_window, 0, 180, psiChanged)

cv2.imshow(messi_0_window, messi_0)
cv2.imshow(messi_grey_window, messi_grey)

cv2.waitKey()
print("Key is now pressed!")

关于python - cv2.imshow() 在自定义函数中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56156199/

相关文章:

c - C中的函数名是什么类型?

opencv - 使用图像序列的 3D 模型

python - 如何使用plotly绘制标准密度曲线?

读取函数内的数据

无法理解函数输出 (C)

64 位 OpenCV 静态链接

c++ - 用DIPlib测量垫圈

python - 如何从同一图像在并行容器中运行不同的 python 脚本

python - 根据 df.query 设置值?

python - 尝试使用 xlsxwriter 将迷你图添加到多行