def main(): # This program will compare two masks for one image. Masks are mutually exclusive but may not complete, in that the foreground is # a subset of all possible foregrounds. Thus, a foreground mask of leaves may not have all leaves selected. # ********************************************************************************************************************* # Open dialog to find the photo subdirectories. # Each subfolder holds mask files (.bmp)that have the same name as each photo (.jpg). # Also, each subfolder should have a number of .csv files that hold the data look-up table frequencies for processing images. # ********************************************************************************************************************* photoPath = fileBrowser('folder', 'Select the photo directory') if photoPath == '': print print "No directory selected, program aborted." print return photoPath = photoPath + '/' ## maskPath = fileBrowser('folder', 'Select the masks directory') ## if maskPath == '': ## print ## print "No directory selected, program aborted." ## print ## return maskDirLocation = fileBrowser('folder', 'Select the foreground mask directory') if maskDirLocation == '': print print "No directory selected, program aborted." print return maskDirLocation = maskDirLocation + '/' backMasksDir = fileBrowser('folder', 'Select the background mask directory') if backMasksDir == '': print print "No directory selected, program aborted." print return backMasksDir = backMasksDir + '/' write256 = True # ********************************************************************************************************************* # Load the 1-D, 2-D, and 3-D color spaces probabilities into a dictionary with the color space tuples (XX), (XX,YY), or (XX,YY,ZZ) as keys # ********************************************************************************************************************* print 'Working on', maskDirLocation fileList = os.listdir(maskDirLocation) # get the mask file names in each subdirectory for csvFile in fileList: # for each color space file... if os.path.splitext(maskDirLocation + '/' + csvFile)[1] == '.csv': # could be other types of files in the subdirectory allPixelMasterArray = [] # for keeping track of pixels in mask allPixelMasterArray.append(['Path and filename','number pixels examined','number of black pixels', 'foremask pixels', 'correct foreground', 'incorrect foreground', 'correct background', 'segments before clean', 'segments after clean', 'foreBigNans', 'QsegFore', 'QsegBack']) box = (0,0) bigForeDataDict = {} # the dictonary that will hold the probabilities foreDataName = (maskDirLocation + '/' + csvFile) print 'Data array name:', csvFile readerFile = open(foreDataName, 'rb') dataReader = csv.reader(readerFile, delimiter = ',') # open the data file headerFlag = 1 for dataItem in dataReader: # File format is: Xcol, [Ycol], frequency, probability, count if headerFlag == 1: # skip the first row, has only header text headerFlag = 0 else: if len(dataItem) == 4: bigForeDataDict[int(float(dataItem[0]))] = float(dataItem[2]) #print int(float(dataItem[0])), float(dataItem[2]), bigForeDataDict[int(float(dataItem[0]))] elif len(dataItem) == 5: bigForeDataDict[(int(float(dataItem[0])),int(float(dataItem[1])))] = float(dataItem[3]) #print int(float(dataItem[0])), int(float(dataItem[1])), float(dataItem[3]), bigForeDataDict[(int(float(dataItem[0])),int(float(dataItem[1])))] elif len(dataItem) == 6: bigForeDataDict[(int(float(dataItem[0])),int(float(dataItem[1])),int(float(dataItem[2])))] = float(dataItem[4]) readerFile.close() if len(dataItem) == 3: tupleFlag = 0 elif len(dataItem) == 4: tupleFlag = 1 # ********************************************************************************************************************* # Start processing individual image files that are associated with masks # ********************************************************************************************************************* for maskFile in fileList: # loop through the files and get the mask files if os.path.splitext(maskDirLocation + '/' + maskFile)[1] == '.bmp': # could be other types of files in the subdirectory foreMaskPathFilename = maskDirLocation + '/' + maskFile backMaskPathFilename = backMasksDir + '/' + maskFile # back mask has same name, different directory imagePathFilename = os.path.splitext(photoPath + maskFile)[0] + '.jpg' # make the path and file name for opening a file in a subdirectory print print 'Processing mask:', maskFile, 'and image:', imagePathFilename foregroundImage = Image.open(imagePathFilename) # open the image and mask files foregroundImage.load() imSize = foregroundImage.size # get image dimensions foregroundSource = foregroundImage.split() # split image into RGB varMaskList = list(foregroundSource[0].getdata()) # list for creating a mask for segmenting (0 or 255) varProbList = [] # list for generating a probability image (0 to 255) foreR = list(foregroundSource[0].getdata()) # get sequential pixel values for every pixel in image foreG = list(foregroundSource[1].getdata()) foreB = list(foregroundSource[2].getdata()) foregroundImage = '' foregroundSource = '' foreBigNans = 0 # if a color is not encountered, keep a record of "NaN's" blackPixelCount = 0 # ********************************************************************************************************************* # convert each pixel RGBs to different color spaces # ********************************************************************************************************************* print 'Converting colors and matching with array...' count = 0 tupleFlag = 0 print csvFile # convert RGBs to different color spaces with range 0 - 255 for each color component (see subroutines) for i in range(0, len(foreR)): # send pixel data to subroutines to calculate colors r = foreR[i]/255.0 g = foreG[i]/255.0 b = foreB[i]/255.0 if not (r == 0 and g == 0 and b == 0): # process only if not black (mask is black) # set the appropriate color component equal to the variables XX, YY, or ZZ for tallying count = count + 1 if csvFile[0:3] == 'RG_': XX = foreR[i] YY = foreG[i] tupleFlag = 1 elif csvFile[0:3] == 'RB_': XX = foreR[i] YY = foreB[i] tupleFlag = 1 elif csvFile[0:3] == 'GB_': XX = foreG[i] YY = foreB[i] tupleFlag = 1 elif csvFile[0:2] == 'R_': XX = foreR[i] elif csvFile[0:2] == 'G_': XX = foreG[i] elif csvFile[0:2] == 'B_': XX = foreB[i] elif csvFile[0:3] == 'BR_': if foreR[i] <> 0: XX = float(foreB[i])/foreR[i] elif csvFile[0:3] == 'GR_': if foreR[i] <> 0: XX = float(foreG[i])/foreR[i] elif csvFile[0:5] == 'GRBR_': if foreR[i] <> 0: XX = float(foreG[i])/foreR[i] YY = float(foreB[i])/foreR[i] tupleFlag = 1 elif csvFile[0:6] == 'RGB3D_': XX = foreR[i] YY = foreG[i] ZZ = foreB[i] tupleFlag = 2 elif csvFile[0:6] == 'HSL_H_': XX, S, L = ColorConverter.rgb_to_HSL(r, g, b, write256) elif csvFile[0:6] == 'HSL_S_': H, XX, L = ColorConverter.rgb_to_HSL(r, g, b, write256) elif csvFile[0:6] == 'HSL_L_': H, S, XX = ColorConverter.rgb_to_HSL(r, g, b, write256) elif csvFile[0:7] == 'HSL_HS_': XX, YY, L = ColorConverter.rgb_to_HSL(r, g, b, write256) tupleFlag = 1 elif csvFile[0:6] == 'Yxy_Y_': XX, x, y = ColorConverter.rgb_to_Yxy(r, g, b, write256) elif csvFile[0:6] == 'Yxy_x_': Y, XX, y = ColorConverter.rgb_to_Yxy(r, g, b, write256) elif csvFile[0:7] == 'Yxy_y2_': Y, x, XX = ColorConverter.rgb_to_Yxy(r, g, b, write256) elif csvFile[0:7] == 'Yxy_xy_': Y, XX, YY = ColorConverter.rgb_to_Yxy(r, g, b, write256) tupleFlag = 1 elif csvFile[0:8] == 'NRGB_NR_': XX, NG, NB = ColorConverter.rgb_to_NRGB(r, g, b, write256) elif csvFile[0:8] == 'NRGB_NG_': NR, XX, NB = ColorConverter.rgb_to_NRGB(r, g, b, write256) elif csvFile[0:8] == 'NRGB_NB_': NR, NG, XX = ColorConverter.rgb_to_NRGB(r, g, b, write256) elif csvFile[0:6] == 'NRGB1_': XX, NRGB_2 = ColorConverter.rbg_to_NRGB_2D(r, g, b, write256) elif csvFile[0:6] == 'NRGB2_': NRGB_1, XX = ColorConverter.rbg_to_NRGB_2D(r, g, b, write256) elif csvFile[0:7] == 'NRGB12_': XX, YY = ColorConverter.rbg_to_NRGB_2D(r, g, b, write256) tupleFlag = 1 elif csvFile[0:6] == 'Lab_L_': XX, a, b2 = ColorConverter.rgb_to_Lab(r, g, b, write256) elif csvFile[0:6] == 'Lab_a_': L2, XX, b2 = ColorConverter.rgb_to_Lab(r, g, b, write256) elif csvFile[0:6] == 'Lab_b_': L2, a, XX = ColorConverter.rgb_to_Lab(r, g, b, write256) elif csvFile[0:7] == 'Lab_ab_': L2, XX, YY = ColorConverter.rgb_to_Lab(r, g, b, write256) tupleFlag = 1 elif csvFile[0:12] == 'Ingling_r_g_': XX, b_y, V3 = ColorConverter.rgb_to_Ingling(r, g, b, write256) elif csvFile[0:12] == 'Ingling_b_y_': r_g, XX, V3 = ColorConverter.rgb_to_Ingling(r, g, b, write256) elif csvFile[0:10] == 'Ingling_V_': r_g, b_y, XX = ColorConverter.rgb_to_Ingling(r, g, b, write256) elif csvFile[0:13] == 'Ingling_rgby_': XX, YY, V3 = ColorConverter.rgb_to_Ingling(r, g, b, write256) tupleFlag = 1 elif csvFile[0:10] == 'ExRGB_R14_': XX, ExR20, ExG, ExB = ColorConverter.rgb_to_ExRGB(r, g, b, write256) elif csvFile[0:10] == 'ExRGB_R20_': ExR14, XX, ExG, ExB = ColorConverter.rgb_to_ExRGB(r, g, b, write256) elif csvFile[0:8] == 'ExRGB_G_': ExR14, ExR20, XX, ExB = ColorConverter.rgb_to_ExRGB(r, g, b, write256) elif csvFile[0:8] == 'ExRGB_B_': ExR14, ExR20, ExG, XX = ColorConverter.rgb_to_ExRGB(r, g, b, write256) elif csvFile[0:7] == 'ExRGB1_': XX, ExRGB_2 = ColorConverter.rgb_to_ExRGB_2D(r, g, b, write256) elif csvFile[0:7] == 'ExRGB2_': ExRGB_1, XX = ColorConverter.rgb_to_ExRGB_2D(r, g, b, write256) elif csvFile[0:8] == 'ExRGB12_': XX, YY = ColorConverter.rgb_to_ExRGB_2D(r, g, b, write256) tupleFlag = 1 elif csvFile[0:7] == 'ATD_A1_': XX, T1, D1, t1, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:7] == 'ATD_T1_': A1, XX, D1, t1, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:7] == 'ATD_D1_': A1, T1, XX, t1, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:6] == 'ATD_t_': A1, T1, D1, XX, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:6] == 'ATD_d_': A1, T1, D1, t1, XX, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:7] == 'ATD_A2_': A1, T1, D1, t1, d1, XX, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:7] == 'ATD_T2_': A1, T1, D1, t1, d1, A2, XX, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:7] == 'ATD_D2_': A1, T1, D1, t1, d1, A2, T2, XX = ColorConverter.rgb_to_ATD(r, g, b, write256) elif csvFile[0:8] == 'ATD_TD1_': A1, XX, YY, t1, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) tupleFlag = 1 elif csvFile[0:8] == 'ATD_TD2_': A1, T1, D1, t1, d1, A2, XX, YY = ColorConverter.rgb_to_ATD(r, g, b, write256) tupleFlag = 1 elif csvFile[0:7] == 'ATD_td_': A1, T1, D1, XX, YY, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) tupleFlag = 1 elif csvFile[0:9] == 'NDI123_1_': XX, NDI2, NDI3 = ColorConverter.rgb_to_NDI123(r, g, b, write256) elif csvFile[0:9] == 'NDI123_2_': NDI1, XX, NDI3 = ColorConverter.rgb_to_NDI123(r, g, b, write256) elif csvFile[0:9] == 'NDI123_3_': NDI1, NDI2, XX = ColorConverter.rgb_to_NDI123(r, g, b, write256) elif csvFile[0:13] == 'NDI123_NDI12_': XX, YY, NDI3 = ColorConverter.rgb_to_NDI123(r, g, b, write256) tupleFlag = 1 elif csvFile[0:13] == 'NDI123_NDI23_': NDI1, XX, YY = ColorConverter.rgb_to_NDI123(r, g, b, write256) tupleFlag = 1 elif csvFile[0:13] == 'NDI123_NDI13_': XX, NDI2, YY = ColorConverter.rgb_to_NDI123(r, g, b, write256) tupleFlag = 1 elif csvFile[0:7] == 'i123_1_': XX, i2, i3 = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) elif csvFile[0:7] == 'i123_2_': i1, XX, i3 = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) elif csvFile[0:7] == 'i123_3_': i1, i2, XX = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) elif csvFile[0:9] == 'i123_i12_': XX, YY, i3 = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) tupleFlag = 1 elif csvFile[0:9] == 'i123_i23_': i1, XX, YY = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) tupleFlag = 1 elif csvFile[0:9] == 'i123_i13_': XX, i2, YY = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) tupleFlag = 1 elif csvFile[0:5] == 'CIVE_': XX = ColorConverter.rgb_to_CIVE(r, g, b, write256) elif csvFile[0:7] == 'shadow_': XX = ColorConverter.rgb_to_shadow(r, g, b, write256) # ********************************************************************************************************************* # find pixel values in the probability array that was imported and add to a list # ********************************************************************************************************************* if tupleFlag == 1: # if the color space is a 2D one, with a tuple describing the data if (int(float(XX)),int(float(YY))) in bigForeDataDict: foreProbability = bigForeDataDict[(int(float(XX)),int(float(YY)))] # grab the probabilities for any pixel from the Big arrays else: foreBigNans = foreBigNans + 1 foreProbability = 0 elif tupleFlag == 0: # if the color space is a 1D one, then one value defines a dictionary entry if int(float(XX)) in bigForeDataDict: foreProbability = bigForeDataDict[int(float(XX))] # grab the probabilities for any pixel from the Big arrays else: foreBigNans = foreBigNans + 1 foreProbability = 0 elif tupleFlag == 2: # 3-d color space if (int(float(XX)),int(float(YY)),int(float(ZZ))) in bigForeDataDict: foreProbability = bigForeDataDict[(int(float(XX)),int(float(YY)),int(float(ZZ)))] else: foreBigNans = foreBigNans + 1 foreProbability = 0 else: # r=0, g=0, b=0: too dark, count as background, but keep track of the number foreProbability = 0 blackPixelCount = blackPixelCount + 1 varProbList.append(foreProbability) # put the probability value into a list for all pixels if foreProbability > 0.5: # create the mask image from the probabilities, > 50% indicates foreground varMaskList[i] = 1 else: varMaskList[i] = 0 print 'Cleaning and segmenting...' # ********************************************************************************************************************* # write the pixels back to image files -- Comment out to not write to disk # ********************************************************************************************************************* ## print 'Saving image files...' ## varMaskList = array(varMaskList) * 255 # put the mask list into the range 0 - 255 ## foregroundImage = Image.new('1', imSize, 'white') ## foregroundImage.putdata(varMaskList) # var list should be 255 for preserve and 0 for black ## ## foregroundImage.save(imagePathFilename + csvFile + '_pixel-masked.bmp') ## foregroundImage = ImageChops.invert(foregroundImage) ## ## varProbList = array(varProbList) * 255 # put the probability list into the range 0 - 255 ## newProbImage = Image.new('L', imSize, 'white') ## newProbImage.putdata(varProbList) # probability list is greyscale ## newProbImage.save(foreMaskPathFilename + csvFile + '_probability.bmp') ## ## varProbList = [] # ********************************************************************************************************************* # Segment Image to count blobs, first before then after removing some "noise" # ********************************************************************************************************************* structElement = array([[1,1,1], [1,1,1], [1,1,1]]) # structuring element used as a mask for determining blobs structDialationElement = array([[0,1,0], [1,1,1], [0,1,0]]) # structuring element used for binary dialation varMaskList = array(varMaskList) # turn to a numpy array varMaskList.resize((imSize[1],imSize[0])) # make it the image shape -- note width x height, not rows x cols! segmentBeforeCount = ndimage.label(varMaskList, structDialationElement)[1] # Count blobs before cleanup # ******************************** # *** Begin removing "noise" *** # ******************************** # remove stray small groups of foreground pixels varMaskList = ndimage.binary_dilation(varMaskList, structure = structDialationElement, iterations = 1) varMaskList = ndimage.binary_erosion(varMaskList, structure = structElement, iterations = 1) # remove pixel noise by eroding one-pass varMaskList = ndimage.binary_erosion(varMaskList, structure = structElement, iterations = 1) varMaskList = ndimage.binary_dilation(varMaskList, structure = structDialationElement, iterations = 1) # add back border pixels in blobs that survived varMaskList = varMaskList.ravel() for i in range(0, len(varMaskList)): # invert the list for the next step if varMaskList[i] > 0: varMaskList[i] = 0 else: varMaskList[i] = 1 varMaskList = array(varMaskList) varMaskList.resize((imSize[1],imSize[0])) varMaskList = ndimage.binary_dilation(varMaskList, structure = structDialationElement, border_value = 1) varMaskList = ndimage.binary_erosion(varMaskList, structure = structElement, border_value = 1) varMaskList = ndimage.binary_erosion(varMaskList, structure = structElement, border_value = 1) varMaskList = ndimage.binary_dilation(varMaskList, structure = structDialationElement, border_value = 1) varMaskList = varMaskList.ravel() for i in range(0, len(varMaskList)): # invert the list for the next step if varMaskList[i] > 0: varMaskList[i] = 0 else: varMaskList[i] = 1 # ****************************** # *** End removing "noise" *** # ****************************** varMaskList = array(varMaskList) varMaskList.resize((imSize[1],imSize[0])) segmentCount = ndimage.label(varMaskList, structDialationElement)[1] # segment the array into continuous regions of increasing integer values, skip the array and return the number of blobs found # ********************************************************************************************************************* # write the pixels back to image files after removing noise -- Comment out to not write to disk # ********************************************************************************************************************* ## print 'Saving image files...' ## varMaskListImage = varMaskList * 255 # put the mask list into the range 0 - 255 ## foregroundImage = Image.new('1', imSize, 'white') ## foregroundImage.putdata(varMaskListImage) # var list should be 255 for preserve and 0 for black ## ## foregroundImage.save(imagePathFilename + csvFile + '_cleaned_pixel-masked.bmp') ## foregroundImage = ImageChops.invert(foregroundImage) ## ## varProbList = array(varProbList) * 255 # put the probability list into the range 0 - 255 ## newProbImage = Image.new('L', imSize, 'white') ## newProbImage.putdata(varProbList) # probability list is greyscale ## newProbImage.save(foreMaskPathFilename + csvFile + '_cleaned_probability.bmp') ## ## varProbList = [] # ********************************************************************************************************************* # compare to the masks to get the correct and incorrect pixel counts of both 'just pixels' and segmented images # ********************************************************************************************************************* print 'Comparing to masks...' foreCount = 0 backCount = 0 badForeCount = 0 badBackCount = 0 foreMaskCount = 0 backMaskCount = 0 QsegFore = 0.0 QsegBack = 0.0 varMaskList = varMaskList.ravel() # turn varMaskList into a linear list of pixels, 0 and 1 of the estimated foreground foreMaskImage = Image.open(foreMaskPathFilename).convert("1") # open the mask image with foreground areas in white, background in black foreMaskList = list(foreMaskImage.getdata()) # turn the foreground mask into a list foreMaskImage = '' backMaskImage = Image.open(backMaskPathFilename).convert("1") # open the mask image with foreground areas in white, background in black backMaskList = list(backMaskImage.getdata()) # turn the foreground mask into a list backMaskImage = '' for i in range(0, len(foreR)): if foreMaskList[i] == 255: # mask says it's foreground foreMaskCount = foreMaskCount + 1 if varMaskList[i] == 1: ### segment says it's foreground. No else statement because there may be correct foreCount = foreCount + 1 ### "foreground" pixles in the background of this mask else: # masks are mutually exclusive, but not complete if backMaskList[i] == 255: # background mask says it's not foreground. No else statement because nothing defined outside of this backMaskCount = backMaskCount + 1 if varMaskList[i] == 1: # segment says it's foreground, a mistake badForeCount = badForeCount + 1 # back foreground count else: # segment correctly says it's not foreground backCount = backCount + 1 # good background count QsegFore = round(foreCount/(foreMaskCount + 0.0001)*100.0, 1) QsegBack = round(backCount/(backMaskCount + 0.0001)*100.0, 1) # ********************************************************************************************************************* # Output stuff # ********************************************************************************************************************* print print 'Color space:', csvFile print 'pixels looked at:', count, ', black pixels:', blackPixelCount, ', sum:', count + blackPixelCount print 'pixels not in big probability array:', foreBigNans print 'pixels in foreground mask:', foreMaskCount print 'correct foreground pixels:', foreCount , '( =', QsegFore, '%)' print 'incorrect foreground pixels:', badForeCount print 'correct background pixels:', backCount, '( =', QsegBack, '%)' print 'blobs before cleanup:', segmentBeforeCount, ', blobs after cleanup:', segmentCount allPixelMasterArray.append([imagePathFilename, count, blackPixelCount, foreMaskCount, foreCount, badForeCount, backCount, segmentBeforeCount, segmentCount, foreBigNans, QsegFore, QsegBack]) print print 'Writing output file...' textPathFilename = maskDirLocation + '/' + csvFile + '_probability_segmented.csv' # file name to write to writerFile = open(textPathFilename, 'wb') writer = csv.writer(writerFile) for i in range(0,len(allPixelMasterArray)): writer.writerow(allPixelMasterArray[i]) writerFile.close()
def main(): ################## Change these flags to modify the program ################# write256 = True # output of color conversion should be scaled, each component, to 0-255 TFcode = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] # 15 RGB_bool = TFcode[0] HSL_bool = TFcode[1] # what color spaces to run Yxy_bool = TFcode[2] NRGB_bool = TFcode[3] NRGB2D_bool = TFcode[4] Lab_bool = TFcode[5] ExRGB_bool = TFcode[6] ATD1_bool = TFcode[7] ATD2_bool = TFcode[8] Atd_bool = TFcode[9] NDI123_bool = TFcode[10] CIVE_bool = TFcode[11] shadow_bool = TFcode[12] i123_bool = TFcode[13] Ingling_bool = TFcode[14] ############################################################################## # Open dialog to find the photo subdirectory. # Assumed: \masks\ holds more folders. # Each subfolder holds mask files that have the same name as each photo, but are bmp's. photoPath = fileBrowser('folder', 'Select directory for photos...') if photoPath == '': print print "No directory selected, program aborted." print return photoPath = photoPath +'\\' photoList = os.listdir(photoPath) foreMaskPathFilename = fileBrowser('file', 'Select the mask file, cancel if no mask.') if foreMaskPathFilename == '': print print "No mask selected." print maskFlag = 0 foreMaskPathFilename = photoPath + '\\junk.csv' else: maskFlag = 1 fileNamePrepend = raw_input('Enter file output name:') print 'Output file will be in mask directory or if no mask, then in photo directory' outFileList = [] colorList = [] header = ['filename','foreground mask pixels','background mask pixles'] writerFile = open(os.path.split(foreMaskPathFilename)[0] + '\\' + fileNamePrepend + '.csv', 'wb') writer = csv.writer(writerFile, delimiter = ',', quoting=csv.QUOTE_NONE) if RGB_bool: outFileList = outFileList + ['RGB'] header = header + ['RGB_R mean','stdev','RGB_G mean','stdev','RGB_B mean','stdev'] if HSL_bool: outFileList = outFileList + ['HSL'] header = header + ['HSL_H mean','stdev','HSL_S mean','stdev','HSL_L mean','stdev'] if Yxy_bool: outFileList = outFileList + ['Yxy'] header = header + ['Yxy_Y mean','stdev','Yxy_x mean','stdev','Yxy_y mean','stdev'] if NRGB_bool: outFileList = outFileList + ['NRGB'] header = header + ['NRGB_NR mean','stdev','NRGB_NG mean','stdev','NRGB_NB mean','stdev'] if NRGB2D_bool: outFileList = outFileList + ['NRGB2D'] header = header + ['NRGB_2D_1 mean','stdev','NRGB_2D_2 mean','stdev'] if Lab_bool: outFileList = outFileList + ['Lab'] header = header + ['Lab_L mean','stdev','Lab_a mean','stdev','Lab_b mean','stdev'] if Ingling_bool: outFileList = outFileList + ['Ingling'] header = header + ['Ingling_V mean','stdev','Ingling_r_g mean','stdev','Ingling_b_y mean','stdev'] if ExRGB_bool: outFileList = outFileList + ['ExRGB'] header = header + ['ExRGB_ExG mean','stdev','ExRGB_1 mean','stdev','ExRGB_2 mean','stdev'] if ATD1_bool: outFileList = outFileList + ['ATD1'] header = header + ['ATD_A1 mean','stdev','ATD_T1 mean','stdev','ATD_D1 mean','stdev'] if Atd_bool: outFileList = outFileList + ['Atd'] header = header + ['Atd_A1 mean','stdev','Atd_t mean','stdev','Atd_d mean','stdev'] if ATD2_bool: outFileList = outFileList + ['ATD2'] header = header + ['ATD_A2 mean','stdev','ATD_T2 mean','stdev','ATD_D2 mean','stdev'] if NDI123_bool: outFileList = outFileList + ['NDI123'] header = header + ['NDI_1 mean','stdev','NDI_2 mean','stdev','NDI_3 mean','stdev'] if i123_bool: outFileList = outFileList + ['i123'] header = header + ['i123_1 mean','stdev','i123_2 mean','stdev','i123_3 mean','stdev'] if CIVE_bool: outFileList = outFileList + ['CIVE'] header = header + ['CIVE mean','stdev'] if shadow_bool: outFileList = outFileList + ['shadow'] header = header + ['shadow mean','stdev'] writer.writerow(header) rowList = [] photoFileIter = iter(photoList) loopFiles = True while loopFiles: # iterate through all the files rowList = [] openFile = True while openFile: # if there are photo files that make the program crash, catch the exception and move to the next try: photoFile = photoFileIter.next() if os.path.splitext(photoPath + photoFile)[1] == '.jpg': # could be other types of files in the subdirectory imagePathFilename = photoPath + photoFile # make the path and file name for opening a file in a subdirectory print print 'Processing image:', imagePathFilename image = Image.open(imagePathFilename) # open the image and mask files image.load() openFile = False except StopIteration: loopFiles = False break except: print print 'Skipped file!', imagePathFilename print if not loopFiles: break # end of file encountered, break out of top while loop rowList = rowList + [imagePathFilename] if maskFlag: # if there is a mask to apply maskImage = Image.open(foreMaskPathFilename).convert("L") # open the mask image with foreground areas in white, background in black else: size = image.size maskImage = Image.new("L",size, 255) maskSource = array(list(maskImage.getdata())) imageSource = image.split() # split image into RGB foreR_original = array(list(imageSource[0].getdata())) # get pixel values for every pixel in image foreG_original = array(list(imageSource[1].getdata())) foreB_original = array(list(imageSource[2].getdata())) foreR = foreR_original # make copies for putting in new color spaces foreG = foreG_original foreB = foreB_original firstColorSpaceFlag = True for colorSpace in outFileList: # one color space at at time print 'Working on', colorSpace Flag2D = 0 Flag1D = 0 foreCount = -1 backCount = 0 # convert RGBs to different color spaces with the output range 0 - 255 for each color component (see subroutines) for i in range(0, len(foreR_original)): # send pixel data to subroutines to calculate colors sys.stdout.write('') if maskSource[i] == 255: # if the pixel is in the foreground of the mask foreCount = foreCount + 1 r = float(foreR_original[i])/255.0 g = float(foreG_original[i])/255.0 b = float(foreB_original[i])/255.0 # ********************* Accumulate ********************************* if colorSpace == 'HSL': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_HSL(r, g, b, write256) elif colorSpace == 'Yxy': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_Yxy(r, g, b, write256) elif colorSpace == 'NRGB': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_NRGB(r, g, b, write256) elif colorSpace == 'NRGB2D': foreR[foreCount], foreG[foreCount] = ColorConverter.rbg_to_NRGB_2D(r, g, b, write256) foreB[foreCount] = 0 Flag2D = 1 elif colorSpace == 'Lab': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_Lab(r, g, b, write256) elif colorSpace == 'Ingling': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_Ingling(r, g, b, write256) elif colorSpace == 'ExRGB': dummy1, dummy2, foreR[foreCount], dummy3 = ColorConverter.rgb_to_ExRGB(r, g, b, write256) foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_ExRGB_2D(r, g, b, write256) elif colorSpace == 'ATD1': foreR[foreCount], foreG[foreCount], foreB[foreCount], dummy1, dummy2, dummy3, dummy4, dummy5 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif colorSpace == 'ATD2': dummy1, dummy2, dummy3, dummy4, dummy5, foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_ATD(r, g, b, write256) elif colorSpace == 'Atd': foreR[foreCount], dummy2, dummy3, foreG[foreCount], foreB[foreCount], dummy4, dummy5, dummy6 = ColorConverter.rgb_to_ATD(r, g, b, write256) elif colorSpace == 'NDI123': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_NDI123(r, g, b, write256) elif colorSpace == 'i123': foreR[foreCount], foreG[foreCount], foreB[foreCount] = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) elif colorSpace == 'CIVE': foreR[foreCount] = ColorConverter.rgb_to_CIVE(r, g, b, write256) foreG[foreCount] = 0 foreB[foreCount] = 0 Flag1D = 1 elif colorSpace == 'shadow': foreR[foreCount] = ColorConverter.rgb_to_shadow(r, g, b, write256) foreG[foreCount] = 0 foreB[foreCount] = 0 Flag1D = 1 else: # pixel is not in foreground in mask backCount = backCount + 1 # *********************************************************************************************** Xmean = mean(foreR[0:foreCount+1]) Ymean = mean(foreG[0:foreCount+1]) Zmean = mean(foreB[0:foreCount+1]) Xstd = std(foreR[0:foreCount+1]) Ystd = std(foreG[0:foreCount+1]) Zstd = std(foreB[0:foreCount+1]) if firstColorSpaceFlag: rowList = rowList + [foreCount+1, backCount] firstColorSpaceFlag = False if ((not Flag2D) and (not Flag1D)): rowList = rowList + [Xmean, Xstd, Ymean, Ystd, Zmean, Zstd] elif Flag2D: rowList = rowList + [Xmean, Xstd, Ymean, Ystd] elif Flag1D: rowList = rowList + [Xmean, Xstd] writer.writerow(rowList) writerFile.close() print 'File closed.'
def main(): ################## Change these flags to modify the program ################# write256 = True # output of color conversion should be scaled, each component, to 0-255 R_G_B_bool = False # what color spaces to run RGBfract_bool = False RGB3D_bool = False HSL_bool = True Yxy_bool = True NRGB_bool = True Lab_bool = True ExRGB_bool = True ATD_bool = True NDI123_bool = True CIVE_bool = True shadow_bool = True i123_bool = True Ingling_bool = True ############################################################################## # Open dialog to find the photo subdirectory. # Assumed: \masks\ holds more folders. # Each subfolder holds mask files that have the same name as each photo, but are bmp's. rootDirName = fileBrowser('folder', 'Select directory for photos...') if rootDirName == '': print print "No directory selected, program aborted." print return photoPath = rootDirName maskPath = rootDirName + '\\masks\\' if not os.path.exists(maskPath): print "No subdirectory called 'masks' found. Program aborted." return maskDirs = [ name for name in os.listdir(maskPath) if os.path.isdir(os.path.join(maskPath, name)) ] if maskDirs == []: print "No subdirectories within \masks\ exists. program aborted." return else: print "Success in finding subdirectories..." ### Start main loop ### for maskDirLocation in maskDirs: print 'Working on', maskDirLocation count = 0.0 maskFileList = os.listdir(maskPath + maskDirLocation) # get the mask file names in each subdirectory outFileList = [] outDictList = [] if RGB3D_bool: outFileList = outFileList + ['RGB3D'] RGB3D = {} outDictList = outDictList + [RGB3D] if R_G_B_bool: outFileList = outFileList + ['R', 'G', 'B'] R = {} G = {} B = {} outDictList = outDictList + [R, G, B] if RGBfract_bool: outFileList = outFileList + ['GR', 'BR', 'GRBR'] GR = {} BR = {} GRBR = {} outDictList = outDictList + [GR, BR, GRBR] if HSL_bool: outFileList = outFileList + ['HSL_H','HSL_S','HSL_L','HSL_HS'] HSL_H = {} HSL_S = {} HSL_L = {} HSL_HS = {} #HSL_HSL = {} outDictList = outDictList + [HSL_H,HSL_S,HSL_L,HSL_HS] if Yxy_bool: outFileList = outFileList + ['Yxy_Y','Yxy_x','Yxy_y2','Yxy_xy'] Yxy_Y = {} Yxy_x = {} Yxy_y2 = {} Yxy_xy = {} #Yxy_Yxy = {} outDictList = outDictList + [Yxy_Y,Yxy_x,Yxy_y2,Yxy_xy] if NRGB_bool: outFileList = outFileList + ['NRGB_NR','NRGB_NG','NRGB_NB','NRGB1','NRGB2','NRGB12'] NRGB_NR = {} NRGB_NG = {} NRGB_NB = {} NRGB1 = {} NRGB2 = {} NRGB12 = {} outDictList = outDictList + [NRGB_NR,NRGB_NG,NRGB_NB,NRGB1,NRGB2,NRGB12] if Lab_bool: outFileList = outFileList + ['Lab_L','Lab_a','Lab_b','Lab_ab'] Lab_L = {} Lab_a = {} Lab_b = {} Lab_ab = {} #Lab_Lab = {} outDictList = outDictList + [Lab_L,Lab_a,Lab_b,Lab_ab] if Ingling_bool: outFileList = outFileList + ['Ingling_r_g','Ingling_b_y','Ingling_rgby','Ingling_V'] Ingling_r_g = {} Ingling_b_y = {} Ingling_rgby = {} Ingling_V = {} outDictList = outDictList + [Ingling_r_g,Ingling_b_y,Ingling_rgby,Ingling_V] if ExRGB_bool: outFileList = outFileList + ['ExRGB_R14','ExRGB_R20','ExRGB_G','ExRGB_B','ExRGB1','ExRGB2','ExRGB12'] ExRGB_R14 = {} ExRGB_R20 = {} ExRGB_G = {} ExRGB_B = {} ExRGB1 = {} ExRGB2 = {} ExRGB12 = {} outDictList = outDictList + [ExRGB_R14,ExRGB_R20,ExRGB_G,ExRGB_B,ExRGB1,ExRGB2,ExRGB12] if ATD_bool: outFileList = outFileList + ['ATD_A1','ATD_T1','ATD_D1','ATD_TD1','ATD_t','ATD_d','ATD_td','ATD_A2','ATD_T2','ATD_D2','ATD_TD2'] ATD_A1 = {} ATD_T1 = {} ATD_D1 = {} ATD_TD1 = {} ATD_t = {} ATD_d = {} ATD_td = {} #ATD_ATD1 = {} ATD_A2 = {} ATD_T2 = {} ATD_D2 = {} ATD_TD2 = {} #ATD_ATD2 = {} outDictList = outDictList + [ATD_A1,ATD_T1,ATD_D1,ATD_TD1,ATD_t,ATD_d,ATD_td,ATD_A2,ATD_T2,ATD_D2,ATD_TD2] if NDI123_bool: outFileList = outFileList + ['NDI123_1','NDI123_2','NDI123_3','NDI123_NDI12','NDI123_NDI23','NDI123_NDI13'] NDI123_1 = {} NDI123_2 = {} NDI123_3 = {} NDI123_NDI12 = {} NDI123_NDI23 = {} NDI123_NDI13 = {} outDictList = outDictList + [NDI123_1,NDI123_2,NDI123_3,NDI123_NDI12,NDI123_NDI23,NDI123_NDI13] if i123_bool: outFileList = outFileList + ['i123_1','i123_2','i123_3','i123_i12','i123_i23','i123_i13'] i123_1 = {} i123_2 = {} i123_3 = {} i123_i12 = {} i123_i23 = {} i123_i13 = {} outDictList = outDictList + [i123_1,i123_2,i123_3,i123_i12,i123_i23,i123_i13] if CIVE_bool: outFileList = outFileList + ['CIVE'] CIVE_val = {} outDictList = outDictList + [CIVE_val] if shadow_bool: outFileList = outFileList + ['shadow'] shadow_val = {} outDictList = outDictList + [shadow_val] for maskFile in maskFileList: if os.path.splitext(maskPath + maskFile)[1] == '.bmp': # could be other types of files in the subdirectory imageFile = photoPath + '\\' + os.path.splitext(maskFile)[0] + '.jpg' print 'Mask: ', maskPath + maskDirLocation + '\\' + maskFile print 'Image:', photoPath + '\\' + os.path.splitext(maskFile)[0] + '.jpg' print maskImage = Image.open(maskPath + maskDirLocation + '\\' + maskFile).convert("L") # open the mask image with foreground areas in white, background in black image = Image.open(imageFile) # open the image file, no mask image.load() image.paste(0, (0,0), ImageChops.invert(maskImage)) # paste the image onto the jpg, need to invert, masking everything but what is wanted #image.save(maskPath + maskDirLocation + '\\' + maskFile + '_masked.jpg') imageSource = image.split() # split image into RGB foreR = list(imageSource[0].getdata()) # get pixel values for every pixel in image foreG = list(imageSource[1].getdata()) foreB = list(imageSource[2].getdata()) # convert RGBs to different color spaces with the output range 0 - 255 for each color component (see subroutines) for i in range(0, len(foreR)): # send pixel data to subroutines to calculate colors if not ((foreR[i] == 0) and ((foreG[i] == 0) and (foreB[i] == 0))): # process only if not black, the mask sys.stdout.write('') r = float(foreR[i])/255.0 g = float(foreG[i])/255.0 b = float(foreB[i])/255.0 count = count + 1.0 # ********************* Accumulate ********************************* ## if RGB_bool: ## RG[(foreR[i],foreG[i])] = RG.get((foreR[i],foreG[i]), 0) + 1 ## RB[(foreR[i],foreB[i])] = RB.get((foreR[i],foreB[i]), 0) + 1 ## GB[(foreG[i],foreB[i])] = GB.get((foreG[i],foreB[i]), 0) + 1 if R_G_B_bool: R[foreR[i]] = R.get(foreR[i], 0) + 1 G[foreG[i]] = G.get(foreG[i], 0) + 1 B[foreB[i]] = B.get(foreB[i], 0) + 1 if RGBfract_bool: if foreR[i] <> 0: GR[float(foreG[i])/foreR[i]] = GR.get(float(foreG[i])/foreR[i], 0) + 1 BR[float(foreB[i])/foreR[i]] = BR.get(float(foreB[i])/foreR[i], 0) + 1 GRBR[(float(foreG[i])/foreR[i], float(foreB[i])/foreR[i])] = GRBR.get((float(foreG[i])/foreR[i], float(foreB[i])/foreR[i]), 0) + 1 else: GR[0.0] = GR.get(0.0, 0) + 1 BR[0.0] = BR.get(0.0, 0) + 1 GRBR[(0.0, 0.0)] = GRBR.get((0.0, 0.0), 0) + 1 if RGB3D_bool: RGB3D[(foreR[i],foreG[i],foreB[i])] = RGB3D.get((foreR[i],foreG[i],foreB[i]), 0) + 1 if HSL_bool: H, S, L = ColorConverter.rgb_to_HSL(r, g, b, write256) HSL_H[H] = HSL_H.get(H, 0) + 1 HSL_S[S] = HSL_S.get(S, 0) + 1 HSL_L[L] = HSL_L.get(L, 0) + 1 HSL_HS[(H,S)] = HSL_HS.get((H,S), 0) + 1 if Yxy_bool: Y, x, y2 = ColorConverter.rgb_to_Yxy(r, g, b, write256) Yxy_Y[Y] = Yxy_Y.get(Y, 0) + 1 Yxy_x[x] = Yxy_x.get(x, 0) + 1 Yxy_y2[y2] = Yxy_y2.get(y2, 0) + 1 Yxy_xy[(x,y2)] = Yxy_xy.get((x,y2), 0) + 1 if NRGB_bool: NR, NG, NB = ColorConverter.rgb_to_NRGB(r, g, b, write256) NRGB_NR[NR] = NRGB_NR.get(NR, 0) + 1 NRGB_NG[NG] = NRGB_NG.get(NG, 0) + 1 NRGB_NB[NB] = NRGB_NB.get(NB, 0) + 1 NRGB_1, NRGB_2 = ColorConverter.rbg_to_NRGB_2D(r, g, b, write256) NRGB1[NRGB_1] = NRGB1.get(NRGB_1, 0) + 1 NRGB2[NRGB_2] = NRGB2.get(NRGB_2, 0) + 1 NRGB12[(NRGB_1, NRGB_2)] = NRGB12.get((NRGB_1, NRGB_2), 0) + 1 if Lab_bool: L2, a, b2 = ColorConverter.rgb_to_Lab(r, g, b, write256) Lab_L[L2] = Lab_L.get(L2, 0) + 1 Lab_a[a] = Lab_a.get(a, 0) + 1 Lab_b[b2] = Lab_b.get(b2, 0) + 1 Lab_ab[(a,b2)] = Lab_ab.get((a,b2), 0) + 1 if Ingling_bool: r_g, b_y, V3 = ColorConverter.rgb_to_Ingling(r, g, b, write256) Ingling_r_g[r_g] = Ingling_r_g.get(r_g, 0) + 1 Ingling_b_y[b_y] = Ingling_b_y.get(b_y, 0) + 1 Ingling_rgby[(r_g,b_y)] = Ingling_rgby.get((r_g,b_y), 0) + 1 Ingling_V[V3] = Ingling_V.get(V3, 0) + 1 if ExRGB_bool: ExR14, ExR20, ExG, ExB = ColorConverter.rgb_to_ExRGB(r, g, b, write256) ExRGB_R14[ExR14] = ExRGB_R14.get(ExR14, 0) + 1 ExRGB_R20[ExR20] = ExRGB_R20.get(ExR20, 0) + 1 ExRGB_G[ExG] = ExRGB_G.get(ExG, 0) + 1 ExRGB_B[ExB] = ExRGB_B.get(ExB, 0) + 1 ExRGB_1, ExRGB_2 = ColorConverter.rgb_to_ExRGB_2D(r, g, b, write256) ExRGB1[ExRGB_1] = ExRGB1.get(ExRGB_1, 0) + 1 ExRGB2[ExRGB_2] = ExRGB2.get(ExRGB_2, 0) + 1 ExRGB12[(ExRGB_1, ExRGB_2)] = ExRGB12.get((ExRGB_1, ExRGB_2), 0) + 1 if ATD_bool: A1, T1, D1, t1, d1, A2, T2, D2 = ColorConverter.rgb_to_ATD(r, g, b, write256) ATD_A1[A1] = ATD_A1.get(A1, 0) + 1 ATD_T1[T1] = ATD_T1.get(T1, 0) + 1 ATD_D1[D1] = ATD_D1.get(D1, 0) + 1 ATD_TD1[(T1,D1)] = ATD_TD1.get((T1,D1), 0) + 1 ATD_t[t1] = ATD_t.get(t1, 0) + 1 ATD_d[d1] = ATD_d.get(d1, 0) + 1 ATD_td[(t1,d1)] = ATD_td.get((t1,d1), 0) + 1 ATD_A2[A2] = ATD_A2.get(A2, 0) + 1 ATD_T2[T2] = ATD_T2.get(T2, 0) + 1 ATD_D2[D2] = ATD_D2.get(D2, 0) + 1 ATD_TD2[(T2,D2)] = ATD_TD2.get((T2,D2), 0) + 1 if NDI123_bool: NDI1, NDI2, NDI3 = ColorConverter.rgb_to_NDI123(r, g, b, write256) NDI123_1[NDI1] = NDI123_1.get(NDI1, 0) + 1 NDI123_2[NDI2] = NDI123_2.get(NDI2, 0) + 1 NDI123_3[NDI3] = NDI123_3.get(NDI3, 0) + 1 NDI123_NDI12[(NDI1, NDI2)] = NDI123_NDI12.get((NDI1, NDI2),0) + 1 NDI123_NDI23[(NDI2, NDI3)] = NDI123_NDI23.get((NDI2, NDI3),0) + 1 NDI123_NDI13[(NDI1, NDI3)] = NDI123_NDI13.get((NDI1, NDI3),0) + 1 if i123_bool: i1, i2, i3 = ColorConverter.rgb_to_i1i2i3(r, g, b, write256) i123_1[i1] = i123_1.get(i1, 0) + 1 i123_2[i2] = i123_2.get(i2, 0) + 1 i123_3[i3] = i123_3.get(i3, 0) + 1 i123_i12[(i1, i2)] = i123_i12.get((i1, i2),0) + 1 i123_i23[(i2, i3)] = i123_i23.get((i2, i3),0) + 1 i123_i13[(i1, i3)] = i123_i13.get((i1, i3),0) + 1 if CIVE_bool: CIVE_value = ColorConverter.rgb_to_CIVE(r, g, b, write256) CIVE_val[CIVE_value] = CIVE_val.get(CIVE_value, 0) + 1 if shadow_bool: shadow_value = ColorConverter.rgb_to_shadow(r, g, b, write256) shadow_val[shadow_value] = shadow_val.get(shadow_value, 0) + 1 # *********************************************************************************************** # write the output files # *********************************************************************************************** print 'Writing output files' print for dictionary in range(0,len(outDictList)): if write256: outputFileName = maskPath + maskDirLocation + '\\' + outFileList[dictionary] + '_256.csv' else: outputFileName = maskPath + maskDirLocation + '\\' + outFileList[dictionary] + '_native.csv' writerFile = open(outputFileName, 'wb') # open the output file and prep writer = csv.writer(writerFile, delimiter = ',',quoting=csv.QUOTE_NONE) newList = [] for i in outDictList[dictionary].iteritems(): # write header to file newList = [] itemCount = 1 if hasattr(i[0], '__iter__'): for ii in i[0]: newList.append('X' + str(itemCount)) itemCount = itemCount + 1 else: newList.append(outFileList[dictionary]) newList = newList + ['count', 'frequency'] writer.writerow(newList) for i in outDictList[dictionary].iteritems(): # write items to file newList = [] if hasattr(i[0], '__iter__'): for ii in i[0]: newList.append(ii) else: newList.append(i[0]) newList.append(i[1]) newList.append(i[1]/count) writer.writerow(newList) writerFile.close() print 'Done!' image = []