3

I am implementing Harris corner detection and having overflow error:

harris.py:27: RuntimeWarning: overflow encountered in ubyte_scalars
  Mat[0][1]=Ix[i][j]*Iy[i][j]
harris.py:28: RuntimeWarning: overflow encountered in ubyte_scalars
  Mat[1][0]=Ix[i][j]*Iy[i][j]

This is the whole source code. Where does the error come from? Since Ix.max is 255 and min is 0.

import cv2
import numpy as np

im=cv2.imread('image.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)

(M,N)=im.shape
print M
print N

Gx=np.array([[1, 0, -1],[ 2, 0, -2], [1, 0, -1]])
Gy=np.array([[1, 2, 1],[0, 0, 0],[-1, -2, -1]])

Ix=cv2.filter2D(im, -1, Gx)
Iy=cv2.filter2D(im, -1, Gy)

print np.max(Ix)
print np.min(Ix)
print np.max(Iy)
print np.min(Iy)

Mat=np.zeros((2,2), dtype='float64')
R=np.zeros((M,N), dtype='float64')
for i in range(M):
    for j in range(N):
        Mat[0][0]=Ix[i][j]**2
        Mat[0][1]=Ix[i][j]*Iy[i][j]
        Mat[1][0]=Ix[i][j]*Iy[i][j]
        Mat[1][1]=Iy[i][j]**2

        R[i][j]=np.linalg.det(Mat)-(np.matrix.trace(Mat))**2


cv2.imshow("Ix",Ix)
cv2.imshow("Iy",Iy)
cv2.imshow("R",R)
cv2.waitKey(0)

1 Answer 1

4

What's happening is that your input data is uint8. Because you're multiplying two uint8's, the result is a uint8, even though it will be upcasted when you assign it to an item in the float array Mat.

As an example:

In [1]: import numpy as np

In [2]: np.uint8(255) * np.uint8(255)
./anaconda/bin/ipython:1: RuntimeWarning: overflow encountered in ubyte_scalars
Out[2]: 1

Notice that numpy will happily return the result (1), but it's not what you might expect if you're not familiar with limited-precision integers.

Newer versions of numpy raise a runtime warning, while older versions with allow it to happen silently.

This is deliberate behavior. It's very useful when dealing with large arrays. You just have to be aware that numpy behaves similar to C when it comes to limited-precision data types.

You have several options.

  1. Cast your entire input array to floating point (e.g. Ix, Iy = Ix.astype(float), Iy.astype(float).
  2. Cast Ix[i][j] and Iy[i][j] to floats inside the loop.
Sign up to request clarification or add additional context in comments.

1 Comment

A possibly better way to do this is to explicitly call the np.multiply function. Then you can specify the output dtype like so: np.multiply(Ix[i][j], Iy[i][j], dtype=np.float64). You can also preallocate an array of the correct type and use the out= form of np.multiply.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.