Reputation: 57
I took on a challenge to implement a few OpenCV functions on my own in Python. Very many of these functions require convolving an image with a kernel, so this is the function I wrote to do that:
def convolve(img, kernel): # img should have zero padding
kx, ky = kernel.shape # kernel is square so kx == ky
start, end = floor(kx / 2), ceil(kx / 2)
x, y = img.shape
convolved = np.zeros((x, y))
for i in range(kx, x - kx):
for j in range(kx, y - kx):
convolved_area = img[i - start:i + end, j - start:j + end] * kernel
convolved[i][j] = np.sum(convolved_area)
return convolved
When I ran this on an image and a kernel that I made, I received a white image with the only color being the black padding.
For testing, the kernel that I used was a Gaussian kernel:
for x in range(radius):
for y in range(radius): # Generate kernel with formula
kernel[x][y] = exp( -0.5 * (pow((x-mean)/sigma, 2.0) + pow((y-mean)/sigma,2.0)) ) / (2 * pi * sigma * sigma)
magnitude += kernel[x][y]
for x in range(radius): # normalize kernel
for y in range(radius):
kernel[x][y] /= magnitude
I know that the kernel works because using OpenCV's filter2D
function worked for me:
convolved = cv2.filter2D(img, -1, kernel)
My question is why doesn't my convolve
function work?
Upvotes: 1
Views: 460
Reputation: 27547
You'll need to specify the datatype of uint8
for the image at
convolved = np.zeros((x, y))
making it
convolved = np.zeros((x, y), 'uint8')
But I would recommend using the np.zeros_like()
method, which takes in an array and returns the array filled with zeros, preserving the original datatype of the array so that you won't have to specify uint8
:
convolved = np.zeros_like(img)
The above is the most practical, but a few alternatives are
convolved = np.zeros((x, y)).astype('uint8')
and
convolved = np.uint8(np.zeros((x, y))
Upvotes: 1