Image Erosion manual implementation not doing anything Python

我是研究僧i 提交于 2021-02-11 12:20:05

问题


Testing image

I write a Python script that manually do a Erosion Morphological Operation to an image using the attached test image, but when I display both the original and altered image, this last one still looks the same even thought is it supposed to be eroded.

I have 3 functions, my Main function, a RGB to Gray Conversion function and the Erosion function.

import cv2
import math
import numpy as np
from PIL import Image, ImageFilter

def main():
    #Read image
    img = cv2.imread('pattern04.bmp')
    #Convert it to gray scale (One color channel)
    imgg = gray(img)
    #Manually create my structuring element (kernel)
    se = [[0,1,0],
          [1,1,1],
          [0,1,0]]
    #Call morphological operation function
    erode(imgg,se)


def erode(im,se):
    rows,columns = im.shape[0], im.shape[1]
    #Initialize counters (Just to keep track)
    fit = 0
    hit = 0
    miss = 0

    #Create a copy of the image to modified it´s pixel values
    ero = im
    #Specify kernel size (w*w)
    w = 3

    #
    for i in range(rows-w-1):
        for j in range(columns-w-1):
            #Get a region (crop) of the image equal to kernel size
            crop = im[i:w+i,j:w+j]
            #Convert region of image to an array
            img = np.array(crop)

            #Get center
            a = math.floor(w/2)
            b = math.floor(w/2)
            
            #Initialize counters 
            matches = 0
            blacks = 0

            #Count number of black pixels (0) and value matches between the two matrix
            for x in range(w):
                for y in range(w):
                    #Count number of black pixels (0)
                    if(img[x][y] == 0):
                        blacks = blacks+1
                        #Count number of matching pixel values between the two matrix   
                        if (img[x][y] == se[x][y]):         
                            matches = matches+1

            #Test if structuring element fit crop image pixels
            #If fit it does nothing because center pixel is already black
            if(matches > 0):
                if(matches == blacks):
                    #Touch
                    fit = fit + 1
                    pass
                #Test if structuring element hit crop image pixels
                #If hit change ero center pixel to black
                elif(matches < blacks):
                    #Hit
                    hit = hit+1
                    ##PROBABLE ERROR IN HERE##
                    ero[a][b] = 0
            #If no pixel match just pass
            else:
                #Miss
                miss=miss+1
                pass

    #Print the number of fits, hits, and misses
    print(str(fit) + '\n' + str(hit) + '\n' + str(miss))

    #Show original gray image and eroded image
    cv2.imshow('Original', im)
    cv2.imshow('Erosion', ero)
    cv2.waitKey(0)


#Function to convert RGB image (3 color channels) to Gray scale (1 color channel)
def gray(img):
    channel = img.shape[2]
    if (channel > 1):
        g_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        return(g_img)
    else:
        return(img)

if __name__ == "__main__":
    main()

What my code does is take the test image, convert it to Gray Scale (just one color channel) and pass to the Erode function. I create a structuring element to work with which is a matrix that will work as my kernel during the process. I crop a region of the gray scale image and convert it to a matrix of the same size of my structuring element (kernel), then, I "overpose" the two matrix to see if any pixel in a specific coordinate of one matrix have the same value in the same coordinate of the second matrix. I create a copy of the gray scale image called ero which is the one I will modified.

There are 3 cases.

1) If all black pixels match, it fits and do nothing

2) If one or more (but not all) black pixels match it fits and it should change the color of the center pixel of ero to black

3) If no pixel match it should do nothing.

I use the first 2 for cycles to crop different regions of the image to pass throught the whole area, the next two for loops are use to iterate over each pixel of the crop image and the kernel and check if the pixels match. **I think the error is in the line marked as

##PROBABLE ERROR IN HERE##

because is the one that specifies to change the color of the central pixel.** (Which is not changing)

If I run the code both images (gray scale original and ero image) look just the same. Any thoughts on what the error could be?


回答1:


Because w never changes, a and b are also always the same. Hence, when you write to the output with ero[a][b] = 0, you are always setting the same pixel to 0. Instead, set the pixel at the center of your window:

ero[i+a][j+b] = 0

Additionally, ero = im causes both variables to reference the same array, modifying the one will modify the other. Create a copy as Mark suggests in a comment:

ero = np.copy(im)

The code might have more issues, I have not tried running it. It certainly can use some vectorization: the loop over x and y can be replace with two vectorized NumPy operations:

blacks = np.coount_nonzero(img == 0)
matches = np.coount_nonzero((img == 0) & (se == 0))

However, assuming both the image and the structuring element only have values of 0 and 255, the erosion operation should be simply written as

ero[i+a][j+b] = np.all(img[se==255]) * 255

That is, the output is set only if all pixels where the SE hits are set. The complication here comes from using numeric arrays with values 0 and 255 instead of logical arrays, which would simplify the expression even further.

The dilation would replace all with any.



来源:https://stackoverflow.com/questions/63098284/image-erosion-manual-implementation-not-doing-anything-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!