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

时间:2019-05-15 19:12:32

标签: python function opencv imshow

OpenCV imshow函数似乎在一个函数外部起作用,但不在该函数内部起作用(而且我认为答案不是waitKey())。为什么会发生这种情况,我该如何解决?

我正在学习2D Gabor小波。为了进行实验和观察,我首先创建了一个内核可视化程序。那是一个非常高兴的JavaScript代码,向我展示了我正在创建的内核。如果您对此感兴趣,我将不胜感激:http://alpersunter.github.io/Gabor2D/

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

我正在使用cv2.createTrackbar()创建滑块,并且在更改任何参数后,跟踪栏将调用“ 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滑块时,新图像会在屏幕上绘制。一切正常。但是,如果我移动psi滑块,则它只会绘制一次,然后停止绘制新图像。有趣的是,如果我再次移动theta并显示另一幅图像,则psi滑块只能再工作一次并再次停止。然后滑动theta,psi再次生效,但仅显示一张图像。

我不知道如何解决此问题,或者这是否与opencv有关。也许是因为我的python不好。无论如何,我希望你能教给我一些新知识。真的很感激我。

1 个答案:

答案 0 :(得分:2)

您的代码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!")