Spaces:
Running
on
Zero
Running
on
Zero
#!/usr/bin/env python | |
import cv2, os, sys | |
import numpy as np | |
def extractImage(path): | |
# error handller if the intended path is not found | |
image = cv2.imread(path, cv2.IMREAD_GRAYSCALE) | |
return image | |
def checkImage(image): | |
""" | |
Args: | |
image: input image to be checked | |
Returns: | |
binary image | |
Raises: | |
RGB image, grayscale image, all-black, and all-white image | |
""" | |
if len(image.shape) > 2: | |
print("ERROR: non-binary image (RGB)"); sys.exit(); | |
smallest = image.min(axis=0).min(axis=0) # lowest pixel value: 0 (black) | |
largest = image.max(axis=0).max(axis=0) # highest pixel value: 1 (white) | |
if (smallest == 0 and largest == 0): | |
print("ERROR: non-binary image (all black)"); sys.exit() | |
elif (smallest == 255 and largest == 255): | |
print("ERROR: non-binary image (all white)"); sys.exit() | |
elif (smallest > 0 or largest < 255 ): | |
print("ERROR: non-binary image (grayscale)"); sys.exit() | |
else: | |
return True | |
class Toolbox: | |
def __init__(self, image): | |
self.image = image | |
def printImage(self): | |
""" | |
Print image into a file for checking purpose | |
unitTest = Toolbox(image); | |
unitTest.printImage(image); | |
""" | |
f = open("image_results.dat", "w+") | |
for i in range(0, self.image.shape[0]): | |
for j in range(0, self.image.shape[1]): | |
f.write("%d " %self.image[i,j]) | |
f.write("\n") | |
f.close() | |
def displayImage(self): | |
""" | |
Display the image on a window | |
Press any key to exit | |
""" | |
cv2.imshow('Displayed Image', self.image) | |
cv2.waitKey(0) | |
cv2.destroyAllWindows() | |
def saveImage(self, title, extension): | |
""" | |
Save as a specific image format (bmp, png, or jpeg) | |
""" | |
cv2.imwrite("{}.{}".format(title,extension), self.image) | |
def morph_open(self, image, kernel): | |
""" | |
Remove all white noises or speckles outside images | |
Need to tune the kernel size | |
Instruction: | |
unit01 = Toolbox(image); | |
kernel = np.ones( (9,9), np.uint8 ); | |
morph = unit01.morph_open(input_image, kernel); | |
""" | |
bin_open = cv2.morphologyEx(self.image, cv2.MORPH_OPEN, kernel) | |
return bin_open | |
def morph_close(self, image, kernel): | |
""" | |
Remove all black noises or speckles inside images | |
Need to tune the kernel size | |
Instruction: | |
unit01 = Toolbox(image); | |
kernel = np.ones( (11,11)_, np.uint8 ); | |
morph = unit01.morph_close(input_image, kernel); | |
""" | |
bin_close = cv2.morphologyEx(self.image, cv2.MORPH_CLOSE, kernel) | |
return bin_close | |
def trimap(image, name, size, number, erosion=False): | |
""" | |
This function creates a trimap based on simple dilation algorithm | |
Inputs [4]: a binary image (black & white only), name of the image, dilation pixels | |
the last argument is optional; i.e., how many iterations will the image get eroded | |
Output : a trimap | |
""" | |
checkImage(image) | |
row = image.shape[0] | |
col = image.shape[1] | |
pixels = 2*size + 1 ## Double and plus 1 to have an odd-sized kernel | |
kernel = np.ones((pixels,pixels),np.uint8) ## Pixel of extension I get | |
if erosion is not False: | |
erosion = int(erosion) | |
erosion_kernel = np.ones((3,3), np.uint8) ## Design an odd-sized erosion kernel | |
image = cv2.erode(image, erosion_kernel, iterations=erosion) ## How many erosion do you expect | |
image = np.where(image > 0, 255, image) ## Any gray-clored pixel becomes white (smoothing) | |
# Error-handler to prevent entire foreground annihilation | |
if cv2.countNonZero(image) == 0: | |
print("ERROR: foreground has been entirely eroded") | |
sys.exit() | |
dilation = cv2.dilate(image, kernel, iterations = 1) | |
dilation = np.where(dilation == 255, 127, dilation) ## WHITE to GRAY | |
remake = np.where(dilation != 127, 0, dilation) ## Smoothing | |
remake = np.where(image > 127, 200, dilation) ## mark the tumor inside GRAY | |
remake = np.where(remake < 127, 0, remake) ## Embelishment | |
remake = np.where(remake > 200, 0, remake) ## Embelishment | |
remake = np.where(remake == 200, 255, remake) ## GRAY to WHITE | |
############################################# | |
# Ensures only three pixel values available # | |
# TODO: Optimization with Cython # | |
############################################# | |
for i in range(0,row): | |
for j in range (0,col): | |
if (remake[i,j] != 0 and remake[i,j] != 255): | |
remake[i,j] = 127 | |
return remake | |
############################################# | |
### TESTING SECTION ### | |
############################################# | |
if __name__ == '__main__': | |
path = "./images/test_images/test_image_11.png" | |
image = extractImage(path) | |
size = 10 | |
number = path[-5] | |
title = "test_image" | |
unit01 = Toolbox(image); | |
kernel1 = np.ones( (11,11), np.uint8 ) | |
unit01.displayImage | |
opening = unit01.morph_close(image,kernel1) | |
trimap(opening, title, size, number, erosion=False) | |
unit02 = Toolbox(opening) | |
unit02.displayImage | |
######################################################## | |
## Default instruction (no binary opening or closing ## | |
## trimap(image, title, size, number, erosion=False); ## | |
######################################################## |