python - 使用 Get2D 在 OpenCV 中访问二维像素值时出现超出范围错误或返回值错误

标签 python image-processing opencv python-imaging-library

这是一个简单的程序,它使用 OpenCV(在 Python 中)导入图像,将其转换为灰度并在窗口中显示。然后,当用户单击窗口中的某个位置时,会从该点执行填充。此外,当用户点击该点时,程序应打印该位置的原始二维像素值。

不幸的是,当太靠右时,OpenCV 会给我一个超出范围的错误,尽管它适用于图像的大部分部分。洪水填充本身在图像中的所有 x-y 位置都正常工作。

在工作区域中,输出如下所示:

mouse at: 70 , 84
Image Size (220, 186)
cv2: (183.0, 0.0, 0.0, 0.0)
pil im: 255

但是当我向右走得太远时,输出看起来像这样:

mouse at: 198 , 129
Image Size (220, 186)
OpenCV Error: One of arguments' values is out of range (index is out of range) in cvGet2D
print "cv2: " +   str(cv2.cv.Get2D(cv2.cv.fromarray(gray), x, y));
cv2.error: index is out of range

我尝试将图像转换为 PIL 图像并使用 Image.getpixel((x,y)) 函数,该函数的工作原理是它没有给我一个超出范围的异常,但不幸的是它返回 255在所有 x-y 点(事实并非如此)。

我尝试将 OpenCV 函数调用 str(cv2.cv.Get2D(cv​​2.cv.fromarray(gray), x, y)) 中 x-y 参数的位置切换为 str(cv2.cv.Get2D(cv​​2. cv.fromarray(gray), y, x)),这消除了超出范围的错误,但导致所有位置的虚假返回 (255.0, 0.0, 0.0, 0.0)。事实上,这个错误的临界点,x 维度 >186,恰好是 y 维度的长度。这是一个主要线索,但没有解决问题(如上所示,我的测试图像大小为 220 x 186)。

import cv2
import cv
import PIL.Image
import numpy

def main():

#mouse event handler flag
CV_EVENT_LBUTTONDOWN = 1;

#THE CODE AT ISSUE IS CONTAINED IN THIS MOUSEHANDLE FUNCTION
def mouseHandle(event, x, y, flag, param):
    if (flag == 1):
        print "mouse is at: " + str(x) + " , " + str(y);
        pilim = Image.fromstring("L", cv.GetSize(cv2.cv.fromarray(gray)),cv2.cv.fromarray(gray).tostring())
        print "Image Size " + str(cv.GetSize(cv.fromarray(gray)))
        print "cv2: " +   str(cv2.cv.Get2D(cv2.cv.fromarray(gray), x, y));
        print "pil im: " + str(pilim.getpixel((x,y)))
        cv2.floodFill(gray,mask,(x,y), (255,255,0),diff,diff)
        cv2.imshow('flood fill',gray)


#THE CODE BELOW IS BASIC OPENCV STUFF TO LOAD THE IMAGE AND INITIATE MOUSECALLS
#reads in the image
im = cv2.imread('image.jpg')

#converts it to grayscale
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
cv2.imshow('grayscale', gray)
cv2.waitKey(0);

# flood fill variables
diff = (6,6,6)
mask = zeros((h+2,w+2),uint8)


# show the result in an OpenCV window, calling setMouseCallBack on mouse click
cv2.imshow('flood fill',gray)
cv2.setMouseCallback('flood fill', mouseHandle, CV_EVENT_LBUTTONDOWN)
cv2.waitKey(0)

test image test image after flood fills (working)

最佳答案

我能够解决这个问题。

首先,关于越界异常。事实证明,cv.Get2D 采用 y,x 形式的像素坐标,这可能会造成混淆。使用行 cv.Get2D(cv​​2.cv.fromarray(gray), y, x));解决越界问题。

其次,关于虚假像素值。这真的很愚蠢,对不起伙计们。由于某种原因,CV_EVENT_LBUTTONDOWN 标志导致 mouseHandle 函数执行两次。我以为我每次单击时都会看到整个输出,但实际上是在填充发生后看到的是 second 输出,这解释了所有位置的 255 值。悲伤但真实!

起初我怀疑我没有正确使用 cv.fromarray,因为 cv2.imread('image.jpg') 返回类型 'numpy.ndarray',而 cv.LoadImage('image.jpg') 返回类型'cv2.cv.iplimage'。我尝试使用 OpenCV1 的 cv.LoadImage('image.jpg') 加载我的图像并使用 cv.FloodFill(im2, (x,y), (255,255,0), diff, diff, 0, cv.fromarray(mask))用于洪水填充(注意 OpenCV 1 和 2 中参数顺序的变化),并使用 cv.Get2D(cv​​2.cv.fromarray(gray), y, x)); 打印 x-y 坐标但问题依然存在。而且,你瞧,答案要简单得多:)

虽然我在调试时确实注意到了一些有趣和奇怪的事情。正如我所提到的,我尝试使用 OpenCV 1 和 OpenCV2 进行洪水填充,但取决于我首先调用的是哪种洪水填充mouseHandle函数,只执行了那个!

下面是一个输出(鼠标点击后)的顺序:

cv2.floodFill(gray,mask,(x,y), (255,255,0),diff,diff)
cv.FloodFill(im2, (x,y), (255,255,0), diff, diff, 0, cv.fromarray(mask))

输出:

mouse at: 202 , 13
(220, 186)
cv2: (35.0, 0.0, 0.0, 0.0)
cv1: (35.0, 0.0, 0.0, 0.0)
pil image: 35
mouse at: 202 , 13
(220, 186)
cv2: (255.0, 0.0, 0.0, 0.0)
cv1: (35.0, 0.0, 0.0, 0.0)
pil image: 255

下面是另一个输出(鼠标点击后)的顺序:

cv.FloodFill(im2, (x,y), (255,255,0), diff, diff, 0, cv.fromarray(mask))
cv2.floodFill(gray,mask,(x,y), (255,255,0),diff,diff)

输出:

mouse at: 137 , 126
(220, 186)
cv2: (146.0, 0.0, 0.0, 0.0)
cv1: (146.0, 0.0, 0.0, 0.0)
pil image: 146
mouse at: 137 , 126
(220, 186)
cv2: (146.0, 0.0, 0.0, 0.0)
cv1: (255.0, 0.0, 0.0, 0.0)
pil image: 146

这两行代码的顺序是我所做的唯一更改!请注意,pil 图像字符串输出遵循 cv2 floodfill 所做的简单操作,因为它包含相同的数据。

关于python - 使用 Get2D 在 OpenCV 中访问二维像素值时出现超出范围错误或返回值错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12764785/

相关文章:

python - Python 中的记忆化、类和多处理

python - 将 Python Pandas 数据帧写入 CSV 文件时出现 Unicode 错误

Python/Flask - 服务器正在接收 POST 请求作为 GET 请求

iphone - 如何对 UIImage 进行像素化?

android - opencv,链接C静态库../lib/armeabi-v7a/liblibjpeg.a

java - cvHaarDetectObjects() 方法有什么作用?

Python 在被 caffe .prototxt 文件作为输入层调用时找不到模块

matlab - 如何绘制由 TrainCascadeObjectDetector 生成的检测器的 ROC 曲线?

c++ - 使用opencv将图像从BGR转换为ARGB

user-interface - 多个OpenCV视频的GUI