4

これは、OpenCV (Python) を使用して画像をインポートし、グレースケールに変換してウィンドウに表示する単純なプログラムです。次に、ユーザーがウィンドウ内の位置をクリックすると、その位置からフラッド フィルが実行されます。さらに、ユーザーがポイントをクリックすると、プログラムは元の 2D ピクセル値をその位置に出力する必要があります。

残念ながら、右に行きすぎると、OpenCV は範囲外のエラーを表示しますが、画像のほとんどの部分で機能します。フラッド フィル自体は、画像内のすべての xy 位置で適切に機能しています。

作業領域では、出力は次のようになります。

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)) 関数を使用しようとしましたが、範囲外の例外が発生しなかったという意味で機能しましたが、残念ながら xyポイント(そうではありません)。

OpenCV関数呼び出し str(cv2.cv.Get2D(cv​​2.cv.fromarray(gray), x, y)) の xy パラメータの位置を str(cv2.cv.Get2D(cv​​2.cv.fromarray) に切り替えてみました(灰色)、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)

テスト画像 塗りつぶし後のテスト画像 (動作中)

4

1 に答える 1

3

問題を解決できました。

まず、範囲外の例外について。 結局のところ、cv.Get2D はピクセル座標を y,x 形式で取得するため、混乱する可能性があります。行 cv.Get2D(cv​​2.cv.fromarray(gray), y, x)); の使用 範囲外の問題を解決しました。

次に、偽のピクセル値についてです。 これは本当にばかげていました、ごめんなさい。何らかの理由で、CV_EVENT_LBUTTONDOWN フラグにより​​、mouseHandle 関数が 2 回実行されます。クリックするたびに出力全体が表示されていると思っていましたが、実際にはフラッド フィルが発生した後の2 番目の出力が表示されていました。これは、すべての位置で 255 の値を説明しています。悲しいけれど事実です!

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)) を使用して xy 座標を出力します。しかし、問題は残りました。そして、見よ、答えははるかに簡単でした:)

ただし、デバッグ中に興味深い奇妙なことに気付きました。 前述したように、OpenCV 1 と OpenCV2 でフラッド フィルを実行しようとしましたが、mouseHandle 関数で最初に呼び出したフラッド フィルによっては、その 1 つだけが実行されました。

以下は、注文を含む出力(マウスクリック後)です。

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

この 2 行のコードの順序は、私が行った唯一の変更です! pil 画像文字列の出力は、同じデータが含まれているため、cv2 フラッドフィルが行っていることに従うことに注意してください。

于 2012-10-08T09:11:06.827 に答える