TheIntegerlol
TheIntegerlol

Reputation: 1

How can I speed up this image mask creation process in python?

I need to create masks for 100.000 images, this code runs on cpu and creates ~500 masks a hour. Is there a way I can speed this up either by parallelising or running code on gpu? I'm okay with solutions that make me heavily rewrite code as long as it speeds up the process.

I tried compiling opencv library myself with cuda support, however I couldn't get most of cv2 methods I use here to run on gpu.

This is my code

Edit #1

Added import list and comments to code.

Added input and output images.

import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
import glob
import sys
import os
import skimage.color
import skimage.filters
import skimage.io
import skimage.viewer


grayScale = cv2.imread(filename,cv2.IMREAD_REDUCED_GRAYSCALE_4)#read image as grayscale with size reduction

kernel = cv2.getStructuringElement(1,(17,17))

blackhat = cv2.morphologyEx(grayScale, cv2.MORPH_BLACKHAT, kernel)

ret,thresh2 = cv2.threshold(blackhat,10,255,cv2.THRESH_BINARY)

dst = cv2.inpaint(newimg,thresh2,1,cv2.INPAINT_TELEA)  #4 lines above are used to remove hair from image

mask = np.zeros(dst.shape[:2],np.uint8)

h,w,c = dst.shape

bgdModel = np.zeros((1,65),np.float64)

fgdModel = np.zeros((1,65),np.float64)

rect = (int(0.1*w),int(0.1*h),int(0.8*w),int(0.8*h))

cv2.grabCut(dst,mask,rect,bgdModel,fgdModel,1,cv2.GC_INIT_WITH_RECT) #removes some background from image
#code for k means clustering starts here

mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')

dst = dst*mask2[:,:,np.newaxis]

vectorized = dst.reshape((-1,3))

vectorized = np.float32(vectorized)

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) #11 lines above are used to remove some background from image

K = 4 
attempts=1

  ret,label,center=cv2.kmeans(vectorized,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)

center = np.uint8(center)

labels = label.flatten()

res = center[label.flatten()]

result_image = res.reshape((dst.shape)) #k means clustering ends here

gray = cv2.cvtColor(result_image, cv2.COLOR_BGR2GRAY)

ret, thresh = cv2.threshold(gray, 10, 20, cv2.THRESH_BINARY)

result_image[thresh == 0] = 255

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))

erosion = cv2.erode(result_image, kernel, iterations = 1)

blur = skimage.color.rgb2gray(erosion)

blur = skimage.filters.gaussian(blur, sigma=float(1)) 

histogram, bin_edges = np.histogram(blur, bins=256, range=(0, 1))

index = next((i for i, x in enumerate(histogram) if x), None)

mask = blur > bin_edges[index+1] #10 lines above are used to create mask

mask = abs(mask-255) #inverts mask

array = np.array(mask, dtype='uint8') 

finimg = cv2.resize(array,None,fx=4.0,fy=4.0) #returns image to original size

plt.imsave("Masks/"+filename, finimg, cmap = plt.cm.gray) #saves result image

input image - skin mole image output image - mask of skin mole

Upvotes: 0

Views: 617

Answers (1)

fmw42
fmw42

Reputation: 53154

You might try using kmeans processing in Python/Opencv as a first step. Then get the inner contour and use that for your mask. Draw the inner contour as white filled on a black background. You may need to use morphology to clean the kmeans results first

Input:

enter image description here

Kmeans 2:

enter image description here

Kmeans 3:

enter image description here

Kmeans 4:

enter image description here

Upvotes: 1

Related Questions