使用Get2D访问OpenCV中的2d像素值时超出范围错误或返回错误值 [英] Out of range error or wrong returned values when accessing 2d pixel values in OpenCV using Get2D

查看:627
本文介绍了使用Get2D访问OpenCV中的2d像素值时超出范围错误或返回错误值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is a simple program that uses OpenCV (in Python) to import an image, convert it to grayscale and display it in a window. Then, when the user clicks a position in the window, a flood-fill is performed from that point. In addition, when the user clicks the point, the program should print the original 2D pixel value at that position.

不幸的是,当到达太远时右边,OpenCV给我一个超出范围的错误,虽然它适用于图像的大部分。洪水填充本身在图像中的所有xy位置都能正常工作。

Unfortunately when too far to the right, OpenCV gives me an out of range error, although it works for most parts of the image. The flood fill itself is working properly at all x-y positions in the image.

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

In working regions the output looks like this:

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

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

But then when I go too far to the right, the output looks like this:

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))函数,它的作用是它没有给我一个超出范围的异常,但不幸的是它在所有xy点返回255(事实并非如此) 。

I tried converting the image to a PIL Image and use the Image.getpixel((x,y)) function, which worked in the sense that it didn't give me an out of range exception, but it unfortunately returns 255 at all x-y points (which is not the case).

我尝试在OpenCV函数调用str中切换xy参数的位置(cv2.cv.Get2D(cv2.cv.fromarray(grey),x,y ))到str(cv2.cv.Get2D(cv2.cv.fromarray(灰色),y,x)),这摆脱了超出范围的误差,但导致虚假的返回(255.0,0.0,0.0) ,0.0)在所有位置。实际上,这个误差的临界点,即x维度中的> 186,确实恰好是y维度的长度。这是一个主要线索,但没有解决问题(我的测试图像大小为220 x 186,如上所示)。

I tried switching the position of the x-y parameters in the OpenCV function call str(cv2.cv.Get2D(cv2.cv.fromarray(gray), x, y)) to str(cv2.cv.Get2D(cv2.cv.fromarray(gray), y, x)), and this got rid of the out of range error, but results in a spurious return of (255.0, 0.0, 0.0, 0.0) at all positions. Indeed, the tipping-point for this error, >186 in the x dimension, does happen to be the length of the y dimension. This is a major clue but does not solve the problem (my test image size is 220 x 186 as you can see above).

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)


推荐答案

我能够解决问题。

首先,关于越界异常。事实证明,cv.Get2D采用y,x形式的像素坐标,这可能令人困惑。使用行cv.Get2D(cv2.cv.fromarray(灰色),y,x));解决了出界问题。

Firstly, regarding the out of bounds exception. As it turns out cv.Get2D takes pixel coordinates in y,x form, which can be confusing. Using the line cv.Get2D(cv2.cv.fromarray(gray), y, x)); solved the out of bounds issue.

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

Secondly, regarding the spurious pixel values. This one was really dumb, sorry guys. For some reason the CV_EVENT_LBUTTONDOWN flag causes the mouseHandle function to execute twice. I thought I was seeing the entire output each time I clicked, but was actually seeing the second output after the flood fill had occurred, which explains the values of 255 at all positions. Sad but true!

起初我怀疑我在某种程度上没有正确使用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打印xy坐标(cv2.cv.fromarray(灰色),y,x));但问题仍然存在。而且,瞧,答案更简单了:)

At first I suspected that I was somehow not using cv.fromarray properly, since cv2.imread('image.jpg') returns type 'numpy.ndarray', and cv.LoadImage('image.jpg') returns type 'cv2.cv.iplimage'. I tried loading my image using OpenCV1's cv.LoadImage('image.jpg') and using cv.FloodFill(im2, (x,y), (255,255,0), diff, diff, 0, cv.fromarray(mask)) for the flood filling (note the changes in parameter order from OpenCV 1 vs 2), and printing the x-y coordinates using cv.Get2D(cv2.cv.fromarray(gray), y, x)); But the problem remained. And, lo and behold, the answer was much simpler :)

当我调试时,我确实注意到一些有趣和奇怪的东西。当我提到过,我尝试用OpenCV 1和OpenCV2填充洪水,但是根据我在mouseHandle函数中首先调用的洪水填充,只执行了一次!

I did notice something interesting and bizarre when I was debugging though. As I mentioned, I tried to do the flood filling with OpenCV 1 and OpenCV2, but depending on which flood fill I called first in the mouseHandle function, only that one executed!

是一个输出(在鼠标点击后)与订单:

Below is an output (after mouseclick) with the order:

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

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

Below is another output (after mouseclick) with the order:

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正在执行的操作,因为它包含相同的数据。

The order of those two lines of code is the only change I made! Note that the pil image string output follows what the cv2 floodfill is doing trivially because it contains the same data.

这篇关于使用Get2D访问OpenCV中的2d像素值时超出范围错误或返回错误值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆