def segmentImage(self, imageData, parameters, saveMaskImage=False): # Requires: -imageData holds 0-1 values of color values (either RGB, HSV, or HLS) # -parameters is three 2-tuple numbers between 0 - 1 that # respectively represent (min, max) color ranges for foreground selection # Effects: returns an RGB mask-list where # (0, 0, 0) is background, (255, 255, 255) is foreground if parameters.colorRanges == None: print "No color range set!" exit(1) colorRanges = parameters.colorRanges # check for bounds errors for tuples in colorRanges: if tuples[0] > tuples[1]: print "Min > Max in parameter!" exit(1) for number in tuples: if not (0 <= number <= 1): print "Parameter not within 0 - 1 range!" exit(1) # xRange either R or H # yRange either G or S # zRange either B or V or L xRange = colorRanges[0] yRange = colorRanges[1] zRange = colorRanges[2] isForeground = lambda x: ( xRange[0] <= x[0] <= xRange[1] and yRange[0] <= x[1] <= yRange[1] and zRange[0] <= x[2] <= zRange[1] ) # if flip bit off, act normally, # else switch background and foreground if parameters.flipBit == False: foreground = (255, 255, 255) background = (0, 0, 0) else: foreground = (0, 0, 0) background = (255, 255, 255) mask = [background] * len(imageData) # mark foreground if in color range for i in range(len(imageData)): if isForeground(imageData[i]): mask[i] = foreground # save image if set true if saveMaskImage == True: dataToImage(mask, parameters.imageSize) return mask
def segmentRegions(self, maskData, parameters, clearWhite = 0, countWhite = False, saveImage = False): # Requires : -maskData is a (0, 0, 0) / (255, 255, 255) # black / white rgb based list data set # -parameters is of type Parameters # -clearWhite is an integer, either 0 or 1 # -countWhite and saveImage is a bool # Effects : -segments a black / white image into distinct # black / white regions and attempts to fill # smaller black regions for increased fit # -if clearWhite set to 1, segmentRegions # will remove any white that is # not connected to the largest sized foreground object # -if countWhite set to True, returns the count of # distinct white / foreground regions bigger than 200 pixels # -if saveImage set to False, segmentRegions does not # save image of new filled image as it does by default imageSize = parameters.imageSize imageMat = imaging.dataToMatrix(maskData, imageSize) # label matrix with "black"/"white" instead of rgb values for convenience for row in range(imageSize[1]): for col in range(imageSize[0]): if imageMat[row][col] == (0, 0, 0): imageMat[row][col] = "black" else: imageMat[row][col] = "white" #list of distinct white / black regions with the count of pixels in each blackRegions = [] whiteRegions = [] blackCount = 0 whiteCount = 0 # flood fill each pixel value with 'black' or 'white', # and mark them with distinct values for row in range(imageSize[1]): for col in range(imageSize[0]): if imageMat[row][col] == "black": blackCount += 1 (count, border) = self.floodFill(imageMat, (col, row), blackCount, parameters) blackRegions.append((count, border)) elif imageMat[row][col] == "white": whiteCount -= 1 (count, border) = self.floodFill(imageMat, (col, row), whiteCount, parameters) whiteRegions.append((count, border)) dataList = imaging.matrixToData(imageMat) # clear out any foreground not connected to the largest piece # of white foreground, executed after recursive call if clearWhite # set to 1 by user if clearWhite == 2: maxWhiteMarked = (whiteRegions.index(max(whiteRegions)) + 1) * -1 for i in range(len(dataList)): if dataList[i] == maxWhiteMarked: dataList[i] = (255,) * 3 else: dataList[i] = (0,) * 3 # any black that is adjacent to border is background # otherwise surrounded by white, foreground else: for i in range(len(dataList)): if dataList[i] > 0 and blackRegions[abs(dataList[i]) - 1][1] == False: dataList[i] = (255,) * 3 elif dataList[i] > 0: dataList[i] = (0,) * 3 else: dataList[i] = (255,) * 3 # count white regions if countWhite == True: totalCount = 0 for i in range(len(whiteRegions)): if whiteRegions[i][0] > 200: totalCount += 1 print "Total foreground count is " + str(totalCount) # if clear white is its non default value of 0, recursively call self # to clear non connecting pieces if clearWhite == 1: self.segmentRegions(dataList, parameters, clearWhite = 2, saveImage = True) # export image if saveImage true # and clearWhite is either 0 or 2 if saveImage == True and clearWhite != 1: imaging.dataToImage(dataList, parameters.imageSize)
def predict(folderName, parameters, segmentAlgo, fitnessFunc, plot=False, exportImages=False): # Requires: -parameters is of type Parameters # -segmentAlgo is of type Segment # -fitnessFunc is of type Fitness # -folder is a string of a folder which contains two subfolders: # -original which contains the original image # -manualsegmentations which contains segmentations # of the original images, the segmentations have the same # name and are of .png format # -plot and export is of type Bool # Effects: -attempts to segment images inside of the speicied folder # based on the single sample image / mask provided to the system # -outputs a histogram plot, "plot-date-time.png", of the fitness # distrubution of the images segmented if plot = True # -saves masks of the segmented images if export = True file_list = glob.glob(folderName + "original/" + "*") prefixLen = len(folderName) + len("original/") suffixLen = len(file_list[0].split(".")[-1]) + 1 fitnessList = [] iteration = 1 for fileName in file_list: image = Image.open(fileName) if parameters.colorSpace in ("hsv", "hls"): imageData = colorSpaceConvert(list(image.getdata()), parameters.colorSpace) else: imageData = colorSpaceConvert(list(image.getdata()), parameters.colorSpace) maskname = fileName[prefixLen:-suffixLen] + ".png" mask = Image.open(folderName + "manualsegmentations/" + maskname) idealMaskData = list(mask.getdata()) parameters.setImageSize(image.size) maskData = segmentAlgo.segmentImage(imageData, parameters, True) fit = fitnessFunc.findFitness(maskData, idealMaskData, parameters) # save mask if export enabled if exportImages == True: dataToImage(maskData, image.size, "-" + str(iteration)) fitnessList.append(fit / float(image.size[0] * image.size[1])) iteration += 1 time = datetime.datetime.now() npFitnessList = numpy.array(fitnessList) mu = npFitnessList.mean() median = numpy.median(npFitnessList) sigma = npFitnessList.std() textstr = '$\overline{x}=%.2f$\n$\mathrm{median}=%.2f$\n$\sigma=%.2f$' % ( mu, median, sigma) fig, ax = pylab.subplots(1) pylab.hist(fitnessList, bins=10) pylab.xlabel('Fitness ratio (Fitness / Image Size)') pylab.ylabel('Number of Images') pylab.title('Number of Images vs. Fitness Ratio') props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) pylab.text(0.78, 0.95, textstr, transform=ax.transAxes, fontsize=14, verticalalignment='top', bbox=props) timeString = "output-" + str(time.month) + '.' + str(time.day) + '.' + str( time.year) timeString += '-' + str(time.hour) + '.' + str(time.minute) pylab.savefig("plotImages" + timeString + ".png")
def predict(folderName, parameters, segmentAlgo, fitnessFunc, plot = False, exportImages = False): # Requires: -parameters is of type Parameters # -segmentAlgo is of type Segment # -fitnessFunc is of type Fitness # -folder is a string of a folder which contains two subfolders: # -original which contains the original image # -manualsegmentations which contains segmentations # of the original images, the segmentations have the same # name and are of .png format # -plot and export is of type Bool # Effects: -attempts to segment images inside of the speicied folder # based on the single sample image / mask provided to the system # -outputs a histogram plot, "plot-date-time.png", of the fitness # distrubution of the images segmented if plot = True # -saves masks of the segmented images if export = True file_list = glob.glob(folderName + "original/" + "*") prefixLen = len(folderName) + len("original/") suffixLen = len(file_list[0].split(".")[-1]) + 1 fitnessList = [] iteration = 1 for fileName in file_list: image = Image.open(fileName) if parameters.colorSpace in ("hsv", "hls"): imageData = colorSpaceConvert(list(image.getdata()), parameters.colorSpace) else: imageData = colorSpaceConvert(list(image.getdata()), parameters.colorSpace) maskname = fileName[prefixLen:-suffixLen] + ".png" mask = Image.open(folderName + "manualsegmentations/" + maskname) idealMaskData = list(mask.getdata()) parameters.setImageSize(image.size) maskData = segmentAlgo.segmentImage(imageData, parameters, True) fit = fitnessFunc.findFitness(maskData, idealMaskData, parameters) # save mask if export enabled if exportImages == True: dataToImage(maskData, image.size, "-" + str(iteration)) fitnessList.append(fit / float(image.size[0] * image.size[1])) iteration += 1 time = datetime.datetime.now() npFitnessList = numpy.array(fitnessList) mu = npFitnessList.mean() median = numpy.median(npFitnessList) sigma = npFitnessList.std() textstr = '$\overline{x}=%.2f$\n$\mathrm{median}=%.2f$\n$\sigma=%.2f$'%(mu, median, sigma) fig, ax = pylab.subplots(1) pylab.hist(fitnessList, bins = 10) pylab.xlabel('Fitness ratio (Fitness / Image Size)') pylab.ylabel('Number of Images') pylab.title('Number of Images vs. Fitness Ratio') props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) pylab.text(0.78, 0.95, textstr, transform=ax.transAxes, fontsize=14, verticalalignment='top', bbox=props) timeString = "output-" + str(time.month) + '.' + str(time.day) + '.' + str(time.year) timeString += '-' + str(time.hour) + '.' + str(time.minute) pylab.savefig("plotImages" + timeString + ".png")
def segmentRegions(self, maskData, parameters, clearWhite=0, countWhite=False, saveImage=False): # Requires : -maskData is a (0, 0, 0) / (255, 255, 255) # black / white rgb based list data set # -parameters is of type Parameters # -clearWhite is an integer, either 0 or 1 # -countWhite and saveImage is a bool # Effects : -segments a black / white image into distinct # black / white regions and attempts to fill # smaller black regions for increased fit # -if clearWhite set to 1, segmentRegions # will remove any white that is # not connected to the largest sized foreground object # -if countWhite set to True, returns the count of # distinct white / foreground regions bigger than 200 pixels # -if saveImage set to False, segmentRegions does not # save image of new filled image as it does by default imageSize = parameters.imageSize imageMat = imaging.dataToMatrix(maskData, imageSize) # label matrix with "black"/"white" instead of rgb values for convenience for row in range(imageSize[1]): for col in range(imageSize[0]): if imageMat[row][col] == (0, 0, 0): imageMat[row][col] = "black" else: imageMat[row][col] = "white" #list of distinct white / black regions with the count of pixels in each blackRegions = [] whiteRegions = [] blackCount = 0 whiteCount = 0 # flood fill each pixel value with 'black' or 'white', # and mark them with distinct values for row in range(imageSize[1]): for col in range(imageSize[0]): if imageMat[row][col] == "black": blackCount += 1 (count, border) = self.floodFill(imageMat, (col, row), blackCount, parameters) blackRegions.append((count, border)) elif imageMat[row][col] == "white": whiteCount -= 1 (count, border) = self.floodFill(imageMat, (col, row), whiteCount, parameters) whiteRegions.append((count, border)) dataList = imaging.matrixToData(imageMat) # clear out any foreground not connected to the largest piece # of white foreground, executed after recursive call if clearWhite # set to 1 by user if clearWhite == 2: maxWhiteMarked = (whiteRegions.index(max(whiteRegions)) + 1) * -1 for i in range(len(dataList)): if dataList[i] == maxWhiteMarked: dataList[i] = (255, ) * 3 else: dataList[i] = (0, ) * 3 # any black that is adjacent to border is background # otherwise surrounded by white, foreground else: for i in range(len(dataList)): if dataList[i] > 0 and blackRegions[abs(dataList[i]) - 1][1] == False: dataList[i] = (255, ) * 3 elif dataList[i] > 0: dataList[i] = (0, ) * 3 else: dataList[i] = (255, ) * 3 # count white regions if countWhite == True: totalCount = 0 for i in range(len(whiteRegions)): if whiteRegions[i][0] > 200: totalCount += 1 print "Total foreground count is " + str(totalCount) # if clear white is its non default value of 0, recursively call self # to clear non connecting pieces if clearWhite == 1: self.segmentRegions(dataList, parameters, clearWhite=2, saveImage=True) # export image if saveImage true # and clearWhite is either 0 or 2 if saveImage == True and clearWhite != 1: imaging.dataToImage(dataList, parameters.imageSize)