noschXL
noschXL

Reputation: 43

Sobel filter implementation in Pygame is not detecting vertical edges but only horizontal ones

I wanted to apply the Sobel filter to an image for edge detection with the vectors and tried it on some test images, but it only marked the vertical edges despite seeing the horizonal edges.

The full code is:

import pygame
import sys
import numpy as np

pygame.init()

def greyscale(surface: pygame.Surface):
    arr = pygame.surfarray.array3d(surface)
    # calulates the avg of the "rgb" values, this reduces the dim by 1
    mean_arr = np.mean(arr, axis=2)
    # restores the dimension from 2 to 3
    mean_arr3d = mean_arr[..., np.newaxis]
    # repeat the avg value obtained before over the axis 2
    new_arr = np.repeat(mean_arr3d[:, :, :], 3, axis=2)
    # return the new surface
    return pygame.surfarray.make_surface(new_arr)


def sobel(path: str, n: int): #path to image, image scale
    img = pygame.image.load(path)
    img = pygame.transform.scale_by(img, n)
    img = greyscale(img)

    imgmap = [[] for _ in range(img.width)]

    for x in range(img.width):
        for y in range(img.height):
            color = img.get_at((x,y)).b
            color = round(color / (255 / 2))
            imgmap[x].append(img.get_at((x,y)).b)

    for x in range(img.width):
        for y in range(img.height):
            Gx, Gy = 0,0
            try:
                Gx = (imgmap[x-1][y + 1] + 2 * imgmap[x-1][y] * imgmap[x-1][y - 1]) - (imgmap[x+1][y + 1] + 2 * imgmap[x+1][y] * imgmap[x+1][y - 1])
            except IndexError:
                pass
            try:
                Gy = (imgmap[x+1][y - 1] + 2 * imgmap[x+1][y] * imgmap[x+1][y + 1]) - (imgmap[x-1][y - 1] + 2 * imgmap[x-1][y] * imgmap[x-1][y + 1])
            except IndexError:
                pass

            if Gx != 0 or Gy != 0:
                pygame.draw.rect(img, "#FF0000", (x,y,1,1))

    return img

if __name__ == "__main__":
    img = sobel("test.png", 3)
    screen = pygame.display.set_mode((img.width, img.height))
    screen.blit(img, (0,0))

    pygame.display.flip()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit

default image image with red edges image with red edges, 3 times bigger

I tried to only draw one (1) edge case at a time, but it always drew the same one.

Upvotes: 0

Views: 53

Answers (1)

noschXL
noschXL

Reputation: 43

I mixed up the lookup for the luminance:

try:
    Gx = (imgmap[x-1][y + 1] + 2 * imgmap[x-1][y] + imgmap[x-1][y - 1]) -   (imgmap[x+1][y + 1] + 2 * imgmap[x+1][y] + imgmap[x+1][y - 1])
except IndexError:
    pass
try:
    Gy = (imgmap[x-1][y - 1] + 2 * imgmap[x][y - 1] + imgmap[x + 1][y - 1]) - (imgmap[x-1][y + 1] + 2 * imgmap[x-1][y] + imgmap[x-1][y - 1])
except IndexError:
    pass

Upvotes: 0

Related Questions