在 PyQt5 中传递 cv2 图像问题
Posted
技术标签:
【中文标题】在 PyQt5 中传递 cv2 图像问题【英文标题】:pass cv2 image issue in PyQt5 【发布时间】:2020-06-10 13:43:24 【问题描述】:我对 pyQt5 并不陌生。当我尝试在函数 pyCharm 中传递图像时,退出代码为 -1073740791 (0xC0000409)。
用 cmd 表示:
_grayImage = _imageToCanny
NameError: name '_imageToCanny' is not defined
似乎如果我在同一个函数中加载带有 imread 的图像,它就可以工作。但是,如果我在不同的函数中加载图像(使用全局),它会说变量为空或给我这个错误。
def doCanny(self):
global _imageToCanny, _grayImage, _edgeResult
global _lowerThreshold, _upperThreshold
#_grayImage = cv2.imread("test.jpg")
_grayImage = _imageToCanny
_grayImage = cv2.cvtColor(_grayImage, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(_grayImage, (3, 3), 0)
_edgeResult = cv2.Canny(blurred, _lowerThreshold, 200)
self.displayImageX(_edgeResult)
代码如下:
'''
import sys
import cv2
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi
class testWin(QMainWindow):
_imageToCanny = None
_grayImage = None
_edgeResult = None
_lowerThreshold = 100
_upperThreshold = 200
_boolX2 = True
_boolX3 = False
_boolXFree = False
_xKernel = 3
_yKernel = 3
def __init__(self):
super(testWin, self).__init__()
loadUi("dlgCannyV2.ui", self)
self.activateSlotPointer()
self.setUI()
def initVariable(self):
global _imageToCanny, _grayImage, _edgeResult
global _lowerThreshold, _upperThreshold
global _boolX2, _boolX3, _boolXFree
global _xKernel, _yKernel
self._imageToCanny = None
self._grayImage = None
self._edgeResult = None
self._lowerThreshold = 100
self._upperThreshold = 200
self._boolX2 = True
self._boolX3 = False
self._boolXFree = False
self._xKernel = 3
self._yKernel = 3
def activateSlotPointer(self):
# VIEWER POINTER
self.viewerCanny = self.findChild(QtWidgets.QLabel, 'viewerCanny')
# BTN POINTER
self.BTN_accept = self.findChild(QtWidgets.QPushButton, 'canny_btnAccept')
self.BTN_cancel = self.findChild(QtWidgets.QPushButton, 'canny_btnCancel')
self.BTN_tryAuto = self.findChild(QtWidgets.QPushButton, 'canny_btnTryAuto')
# SLIDER POINTER
self.SLD_LowerValue = self.findChild(QtWidgets.QSlider, 'canny_sldLowThreshold')
self.SLD_UpperValue = self.findChild(QtWidgets.QSlider, 'canny_sldUpperThreshold')
# LBL POINTER
self.LBL_lowerValue = self.findChild(QtWidgets.QLabel, 'canny_lbLowThreshold')
self.LBL_upperValue = self.findChild(QtWidgets.QLabel, 'canny_lblUpperThreshold')
# LBL POINTER
self.RAD_X2 = self.findChild(QtWidgets.QRadioButton, 'canny_chkX2')
self.RAD_X3 = self.findChild(QtWidgets.QRadioButton, 'canny_chkX3')
self.RAD_XFREE = self.findChild(QtWidgets.QRadioButton, 'canny_chkXFree')
def setUI(self):
self.setWindowTitle("test PyQt5 with MAtPlotlib")
global _lowerThreshold, _upperThreshold
# Button -> Function
self.BTN_accept.clicked.connect(self.doAccept)
self.BTN_cancel.clicked.connect(self.doCancel)
self.BTN_tryAuto.clicked.connect(self.doTryAuto)
# Slider -> Function
self.SLD_LowerValue.setProperty('maximum', 500)
self.SLD_LowerValue.valueChanged.connect(self.setLowerThreshold)
self.SLD_LowerValue.setValue(self._lowerThreshold)
self.SLD_UpperValue.setProperty('maximum', 500)
self.SLD_UpperValue.valueChanged.connect(self.setUpperThreshold)
self.SLD_UpperValue.setValue(self._upperThreshold)
# Label -> Function
self.LBL_lowerValue.setText(str(self._lowerThreshold))
self.LBL_upperValue.setText(str(self._upperThreshold))
# RadioButton -> Function
self.RAD_X2.setChecked(False)
self.RAD_X3.setChecked(False)
self.RAD_XFREE.setChecked(True)
def setImage(self, image=None):
global _imageToCanny, _grayImage, _edgeResult
_imageToCanny = image
_grayImage = _imageToCanny.copy()
_edgeResult = _imageToCanny.copy()
self.displayImageX(_imageToCanny)
def doAccept(self):
pass
def doCancel(self):
self.close()
def doTryAuto(self):
pass
def setLowerThreshold(self):
global _lowerThreshold,_upperThreshold
_lowerThreshold = self.SLD_LowerValue.value()
_upperThreshold = self.SLD_UpperValue.value()
self.LBL_lowerValue.setText(str(_lowerThreshold))
self.doCanny()
def setUpperThreshold(self):
global _lowerThreshold,_upperThreshold
_lowerThreshold = self.SLD_LowerValue.value()
_upperThreshold = self.SLD_UpperValue.value()
self.LBL_upperValue.setText(str(_upperThreshold))
self.doCanny()
def x2Select(self):
if self.RAD_X2.setChecked(False):
self.RAD_X2.setChecked(True)
self.RAD_X3.setChecked(False)
self.RAD_XFREE.setChecked(False)
def x3Select(self):
if self.RAD_X3.setChecked(False):
self.RAD_X3.setChecked(True)
self.RAD_X2.setChecked(False)
self.RAD_XFREE.setChecked(False)
def xFreeSelect(self):
if self.RAD_XFREE.setChecked(False):
self.RAD_Xq.setChecked(False)
self.RAD_X2.setChecked(False)
self.RAD_XFREE.setChecked(True)
# function from:
# https://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/
#
##################################
#
# CANNY PROCESSING
#
##################################
def doCanny(self):
global _imageToCanny, _grayImage, _edgeResult
global _lowerThreshold, _upperThreshold
#_grayImage = cv2.imread("test.jpg")
_grayImage = _imageToCanny
_grayImage = cv2.cvtColor(_grayImage, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(_grayImage, (3, 3), 0)
_edgeResult = cv2.Canny(blurred, _lowerThreshold, 200)
self.displayImageX(_edgeResult)
##################################
#
# GRAPHIC ENGINE
#
##################################
def testImage(self):
pixmap = QPixmap('test.jpg')
self.viewerCanny.setPixmap(pixmap)
# self.resize(pixmap.width(), pixmap.height())
def displayImageX(self, image):
qformat = QImage.Format_Indexed8
if len(image.shape) == 3: # rows[0],cols[1],channels[2]
if (image.shape[2]) == 4:
qformat = QImage.Format_RGBA8888
else:
qformat = QImage.Format_RGB888
img = QImage(image, image.shape[1], image.shape[0], image.strides[0], qformat)
# BGR > RGB
img = img.rgbSwapped()
self.viewerCanny.setPixmap(QPixmap.fromImage(img))
self.viewerCanny.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)
app = QApplication(sys.argv)
win = testWin()
image = cv2.imread("test.jpg", cv2.IMREAD_ANYCOLOR)
win.setImage(image)
win.show()
sys.exit(app.exec_())
'''
这是 dlgCannyV2.ui:
'''
【问题讨论】:
建议:在 /CMD 控制台中运行您的脚本,因为您将获得比数字代码更具描述性的错误消息 1) 提供minimal reproducible example,2) 使用image = cv2.imread("/full/path/of/test.jpg", cv2.IMREAD_ANYCOLOR)
【参考方案1】:
看来主要问题在于环境。我不知道为什么,但它弄乱了全局变量。我重新开始使用一个新的虚拟环境进行了一些测试,现在它可以工作了......
'''
import cv2
class testClass():
_testVariable = None
def __init__(self):
pass
def setValue(self, value):
global _testVariable
_testVariable = value
def func(self):
global _testVariable
_testVariable = 12
def printValue(self):
global _testVariable
print (_testVariable)
#######
test = testClass()
test.func()
test.printValue()
image = cv2.imread("test.jpg")
test.setValue(image)
test.printValue()
'''
【讨论】:
以上是关于在 PyQt5 中传递 cv2 图像问题的主要内容,如果未能解决你的问题,请参考以下文章