user4567366
user4567366

Reputation:

Variable changes after loop

I have the following code:

    """
    Parameters
    ----------
    image : numpy.ndarray(dtype=np.uint8)
        A grayscale image represented in a numpy array.

    kernel : numpy.ndarray
        A kernel represented in a numpy array of size (k, k) where k is an odd
        number strictly greater than zero.

    Returns
    -------
    output : numpy.ndarray(dtype=np.float64)
        The output image. The size of the output array should be smaller than
        the original image size by k-1 rows and k-1 columns, where k is the
        size of the kernel.
    """


    #kernel is of shape (K x K), square
    K = kernel.shape[0]

    #create a result array with K+1 rows and columns
    result = np.zeros([image.shape[0] - K + 1, image.shape[1] - K + 1], dtype=np.float64)

    #loop through the image
    for r in range(result.shape[0]):
        for c in range(result.shape[1]):
            avg = 0 #running average for this image pixel

            #loop through the kernel
            for kr in range(kernel.shape[0]):
                for kc in range(kernel.shape[1]):
                    avg += image[r][c] * kernel[kr][kc]
                    print avg #values are as expected

            print avg #values are rounded (i.e. no decimals)
            result[r][c] = avg

    return result

I'm trying to perform Cross Correlation in 2D using this formula. I can't figure out why my numbers are being rounded inexplicably. I'm somewhat new to Python so maybe I'm doing something wrong.

I'd appreciate any and all help.

Edit: I'm expecting to have my output equal identical output of the following cv2 function call:

GAUSSIAN_KERNEL = np.array([[  1,  4,  6,  4,  1],
                                    [  4, 16, 24, 16,  4],
                                    [  6, 24, 36, 24,  6],
                                    [  4, 16, 24, 16,  4],
                                    [  1,  4,  6,  4,  1]], dtype=np.float64) / 256.

        N = GAUSSIAN_KERNEL.shape[0] // 2

        tested = a4.crossCorrelation2D(self.testImage, GAUSSIAN_KERNEL)

        goal = cv2.filter2D(self.testImage, cv2.CV_64F, GAUSSIAN_KERNEL)[N:-N, N:-N]
        assert np.testing.assert_array_equal(tested, goal, "Arrays were not equal")

Upvotes: 0

Views: 145

Answers (1)

caspillaga
caspillaga

Reputation: 563

Note that in this loop extracted from you code:

avg = 0
for kr in range(kernel.shape[0]):
    for kc in range(kernel.shape[1]):
        avg += image[r][c] * kernel[kr][kc]

avg will always add up to image[r][c], because you are doing

image[r][c] * kernel[0][0] + image[r][c] * kernel[0][1] + image[r][c] * kernel[0][2]...

which is equal to

image[r][c] * (kernel[0][0] + kernel[0][1] + kernel[0][2]...)

which is equal to

image[r][c] * sum-of-all-kernel-elements

which is equal to

image[r][c] * 1.0

The correct loop should be something like this:

for r in range(result.shape[0]):
    for c in range(result.shape[1]):
        avg = 0.0
        for kr in range(kernel.shape[0]):
            for kc in range(kernel.shape[1]):
                avg += kernel[kr][kc] * image[r+kr][c+kc]
        result[r][c] = np.uint(avg)

I haven't tested my code yet, but I think you may need just small adjusments

Upvotes: 1

Related Questions