def process_pot(self, pot_image): device = 0 # debug=None updated_pot_image = self.threshold_green(pot_image) # plt.imshow(updated_pot_image) # plt.show() device, a = pcv.rgb2gray_lab(updated_pot_image, 'a', device) device, img_binary = pcv.binary_threshold(a, 127, 255, 'dark', device, None) # plt.imshow(img_binary) # plt.show() mask = np.copy(img_binary) device, fill_image = pcv.fill(img_binary, mask, 50, device) device, dilated = pcv.dilate(fill_image, 1, 1, device) device, id_objects, obj_hierarchy = pcv.find_objects( updated_pot_image, updated_pot_image, device) device, roi1, roi_hierarchy = pcv.define_roi(updated_pot_image, 'rectangle', device, None, 'default', debug, False) device, roi_objects, hierarchy3, kept_mask, obj_area = pcv.roi_objects( updated_pot_image, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) device, obj, mask = pcv.object_composition(updated_pot_image, roi_objects, hierarchy3, device, debug) device, shape_header, shape_data, shape_img = pcv.analyze_object( updated_pot_image, "Example1", obj, mask, device, debug, False) print(shape_data[1])
def main(): # Get options args = options() debug = args.debug # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 device, corrected_img = pcv.white_balance(device, img, debug, (500, 1000, 500, 500)) img = corrected_img device, img_gray_sat = pcv.rgb2gray_lab(img, 'a', device, debug) device, img_binary = pcv.binary_threshold(img_gray_sat, 120, 255, 'dark', device, debug) mask = np.copy(img_binary) device, fill_image = pcv.fill(img_binary, mask, 300, device, debug) device, id_objects, obj_hierarchy = pcv.find_objects( img, fill_image, device, debug) device, roi, roi_hierarchy = pcv.define_roi(img, 'rectangle', device, None, 'default', debug, True, 1800, 1600, -1500, -500) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi, roi_hierarchy, id_objects, obj_hierarchy, device, debug) device, obj, mask = pcv.object_composition(img, roi_objects, roi_obj_hierarchy, device, debug) outfile = os.path.join(args.outdir, filename) device, color_header, color_data, color_img = pcv.analyze_color( img, img, mask, 256, device, debug, None, 'v', 'img', 300, outfile) device, shape_header, shape_data, shape_img = pcv.analyze_object( img, "img", obj, mask, device, debug, outfile) shapepath = outfile[:-4] + '_shapes.jpg' shapepic = cv2.imread(shapepath) plantsize = "The plant is " + str(np.sum(mask)) + " pixels large" cv2.putText(shapepic, plantsize, (500, 500), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 255, 0), 10) pcv.print_image(shapepic, outfile[:-4] + '-out_shapes.jpg')
def read_dot(self, imageread): img1 = imageread device, img1gray = pcv.rgb2gray(img1, 0) img1hsv = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV) dev, img_binary = pcv.binary_threshold(img1gray, 1, 255, 'light', 0) device, id_objects, obj_hierarchy = pcv.find_objects( img1, img_binary, 0) device, roi, roi_hierarchy = pcv.define_roi(img1, shape="rectangle", device=device, roi_input="default", adjust=False, x_adj=600, y_adj=600, w_adj=1200, h_adj=1200) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img1, "partial", roi, roi_hierarchy, id_objects, obj_hierarchy, device) device, clusters_i, contours, obj_hierarchy = pcv.cluster_contours( device=device, img=img1, roi_objects=roi_objects, roi_obj_hierarchy=roi_obj_hierarchy, nrow=1, ncol=int(3)) dotQ = list() obj_hierarchy = obj_hierarchy[0] for clusters1 in clusters_i: for contourtocheck in clusters1: if not obj_hierarchy[contourtocheck][2] == -1: if not cv2.contourArea( contours[obj_hierarchy[contourtocheck][2]]) >= 20: obj_hierarchy[contourtocheck][2] = -1 counter = 0 for foundcontour in clusters_i: hierarchycontours = [obj_hierarchy[j][2] for j in foundcontour] if not all([bool(j == -1) for j in hierarchycontours]): dotQ.append(True) else: dotQ.append(False) return dotQ
def plant_cv(img): counter = 0 debug = None counter, s = pcv.rgb2gray_hsv(img, 's', counter, debug) counter, s_thresh = pcv.binary_threshold(s, 145, 255, 'light', counter, debug) counter, s_mblur = pcv.median_blur(s_thresh, 5, counter, debug) # Convert RGB to LAB and extract the Blue channel counter, b = pcv.rgb2gray_lab(img, 'b', counter, debug) # Threshold the blue image counter, b_thresh = pcv.binary_threshold(b, 145, 255, 'light', counter, debug) counter, b_cnt = pcv.binary_threshold(b, 145, 255, 'light', counter, debug) # Join the thresholded saturation and blue-yellow images counter, bs = pcv.logical_or(s_mblur, b_cnt, counter, debug) counter, masked = pcv.apply_mask(img, bs, 'white', counter, debug) #---------------------------------------- # Convert RGB to LAB and extract the Green-Magenta and Blue-Yellow channels counter, masked_a = pcv.rgb2gray_lab(masked, 'a', counter, debug) counter, masked_b = pcv.rgb2gray_lab(masked, 'b', counter, debug) # Threshold the green-magenta and blue images counter, maskeda_thresh = pcv.binary_threshold(masked_a, 115, 255, 'dark', counter, debug) counter, maskeda_thresh1 = pcv.binary_threshold(masked_a, 135, 255, 'light', counter, debug) counter, maskedb_thresh = pcv.binary_threshold(masked_b, 128, 255, 'light', counter, debug) # Join the thresholded saturation and blue-yellow images (OR) counter, ab1 = pcv.logical_or(maskeda_thresh, maskedb_thresh, counter, debug) counter, ab = pcv.logical_or(maskeda_thresh1, ab1, counter, debug) counter, ab_cnt = pcv.logical_or(maskeda_thresh1, ab1, counter, debug) # Fill small objects counter, ab_fill = pcv.fill(ab, ab_cnt, 200, counter, debug) # Apply mask (for vis images, mask_color=white) counter, masked2 = pcv.apply_mask(masked, ab_fill, 'white', counter, debug) zeros = np.zeros(masked2.shape[:2], dtype="uint8") merged = cv2.merge([zeros, ab_fill, zeros]) return merged, masked2
def main(): # Get options args = options() debug = args.debug # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 device, img1 = pcv.white_balance(device, img, debug, (100, 100, 1000, 1000)) img = img1 #seedmask, path1, filename1 = pcv.readimage(args.mask) #device, seedmask = pcv.rgb2gray(seedmask, device, debug) #device, inverted = pcv.invert(seedmask, device, debug) #device, masked_img = pcv.apply_mask(img, inverted, 'white', device, debug) device, img_gray_sat = pcv.rgb2gray_hsv(img1, 's', device, debug) device, img_binary = pcv.binary_threshold(img_gray_sat, 70, 255, 'light', device, debug) img_binary1 = np.copy(img_binary) device, fill_image = pcv.fill(img_binary1, img_binary, 300, device, debug) device, seed_objects, seed_hierarchy = pcv.find_objects( img, fill_image, device, debug) device, roi1, roi_hierarchy1 = pcv.define_roi(img, 'rectangle', device, None, 'default', debug, True, 1500, 1000, -1000, -500) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img, 'partial', roi1, roi_hierarchy1, seed_objects, seed_hierarchy, device, debug) img_copy = np.copy(img) for i in range(0, len(roi_objects)): rand_color = pcv.color_palette(1) cv2.drawContours(img_copy, roi_objects, i, rand_color[0], -1, lineType=8, hierarchy=roi_obj_hierarchy) pcv.print_image( img_copy, os.path.join(args.outdir, filename[:-4]) + "-seed-confetti.jpg") shape_header = [] # Store the table header table = [] # Store the PlantCV measurements for each seed in a table for i in range(0, len(roi_objects)): if roi_obj_hierarchy[0][i][ 3] == -1: # Only continue if the object is an outermost contour # Object combine kept objects # Inputs: # contours = object list # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, obj, mask = pcv.object_composition( img, [roi_objects[i]], np.array([[roi_obj_hierarchy[0][i]]]), device, None) if obj is not None: # Measure the area and other shape properties of each seed # Inputs: # img = image object (most likely the original), color(RGB) # imgname = name of image # obj = single or grouped contour object # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. # filename = False or image name. If defined print image device, shape_header, shape_data, shape_img = pcv.analyze_object( img, "img", obj, mask, device, None) if shape_data is not None: table.append(shape_data[1]) data_array = np.array(table) maxval = np.argmax(data_array) maxseed = np.copy(img) cv2.drawContours(maxseed, roi_objects, maxval, (0, 255, 0), 10) imgtext = "This image has " + str(len(data_array)) + " seeds" sizeseed = "The largest seed is in green and is " + str( data_array[maxval]) + " pixels" cv2.putText(maxseed, imgtext, (500, 300), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 0, 0), 10) cv2.putText(maxseed, sizeseed, (500, 600), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 0, 0), 10) pcv.print_image(maxseed, os.path.join(args.outdir, filename[:-4]) + "-maxseed.jpg")
def report_size_marker_area(img, shape, device, debug, marker='define', x_adj=0, y_adj=0, w_adj=0, h_adj=0, base='white', objcolor='dark', thresh_channel=None, thresh=None, filename=False): """Outputs numeric properties for an input object (contour or grouped contours). Inputs: img = image object (most likely the original), color(RGB) shape = 'rectangle', 'circle', 'ellipse' device = device number. Used to count steps in the pipeline debug = None, print, or plot. Print = save to file, Plot = print to screen. marker = define or detect, if define it means you set an area, if detect it means you want to detect within an area x_adj = x position of shape, integer y_adj = y position of shape, integer w_adj = width h_adj = height plantcv = background color 'white' is default objcolor = object color is 'dark' or 'light' thresh_channel = 'h', 's','v' thresh = integer value filename = name of file Returns: device = device number marker_header = shape data table headers marker_data = shape data table values analysis_images = list of output images :param img: numpy array :param shape: str :param device: int :param debug: str :param marker: str :param x_adj:int :param y_adj:int :param w_adj:int :param h_adj:int :param h_adj:int :param base:str :param objcolor: str :param thresh_channel:str :param thresh:int :param filename: str :return: device: int :return: marker_header: str :return: marker_data: int :return: analysis_images: list """ device += 1 ori_img = np.copy(img) if len(np.shape(img)) == 3: ix, iy, iz = np.shape(img) else: ix, iy = np.shape(img) size = ix, iy roi_background = np.zeros(size, dtype=np.uint8) roi_size = (ix - 5), (iy - 5) roi = np.zeros(roi_size, dtype=np.uint8) roi1 = roi + 1 roi_contour, roi_heirarchy = cv2.findContours(roi1, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:] cv2.drawContours(roi_background, roi_contour[0], -1, (255, 0, 0), 5) if (x_adj > 0 and w_adj > 0) or (y_adj > 0 and h_adj > 0): fatal_error( 'Adjusted ROI position is out of frame, this will cause problems in detecting objects' ) for cnt in roi_contour: size1 = ix, iy, 3 background = np.zeros(size1, dtype=np.uint8) if shape == 'rectangle' and (x_adj >= 0 and y_adj >= 0): x, y, w, h = cv2.boundingRect(cnt) x1 = x + x_adj y1 = y + y_adj w1 = w + w_adj h1 = h + h_adj cv2.rectangle(background, (x1, y1), (x + w1, y + h1), (1, 1, 1), -1) elif shape == 'circle': x, y, w, h = cv2.boundingRect(cnt) x1 = x + x_adj y1 = y + y_adj w1 = w + w_adj h1 = h + h_adj center = (int((w + x1) / 2), int((h + y1) / 2)) if h > w: radius = int(w1 / 2) cv2.circle(background, center, radius, (1, 1, 1), -1) else: radius = int(h1 / 2) cv2.circle(background, center, radius, (1, 1, 1), -1) elif shape == 'ellipse': x, y, w, h = cv2.boundingRect(cnt) x1 = x + x_adj y1 = y + y_adj w1 = w + w_adj h1 = h + h_adj center = (int((w + x1) / 2), int((h + y1) / 2)) if w > h: cv2.ellipse(background, center, (int(w1 / 2), int(h1 / 2)), 0, 0, 360, (1, 1, 1), -1) else: cv2.ellipse(background, center, (int(h1 / 2), int(w1 / 2)), 0, 0, 360, (1, 1, 1), -1) else: fatal_error('Shape' + str(shape) + ' is not "rectangle", "circle", or "ellipse"!') markerback = cv2.cvtColor(background, cv2.COLOR_RGB2GRAY) shape_contour, hierarchy = cv2.findContours(markerback, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)[-2:] cv2.drawContours(ori_img, shape_contour, -1, (255, 255, 0), 5) if debug is 'print': print_image(ori_img, (str(device) + '_marker_roi.png')) elif debug is 'plot': plot_image(ori_img) if marker == 'define': m = cv2.moments(markerback, binaryImage=True) area = m['m00'] device, id_objects, obj_hierarchy = find_objects( img, markerback, device, debug) device, obj, mask = object_composition(img, id_objects, obj_hierarchy, device, debug) center, axes, angle = cv2.fitEllipse(obj) major_axis = np.argmax(axes) minor_axis = 1 - major_axis major_axis_length = axes[major_axis] minor_axis_length = axes[minor_axis] eccentricity = np.sqrt(1 - (axes[minor_axis] / axes[major_axis])**2) elif marker == 'detect': if thresh_channel is not None and thresh is not None: if base == 'white': masked = cv2.multiply(img, background) marker1 = markerback * 255 mask1 = cv2.bitwise_not(marker1) markstack = np.dstack((mask1, mask1, mask1)) added = cv2.add(masked, markstack) else: added = cv2.multiply(img, background) device, maskedhsv = rgb2gray_hsv(added, thresh_channel, device, debug) device, masked2a_thresh = binary_threshold(maskedhsv, thresh, 255, objcolor, device, debug) device, id_objects, obj_hierarchy = find_objects( added, masked2a_thresh, device, debug) device, roi1, roi_hierarchy = define_roi(added, shape, device, None, 'default', debug, True, x_adj, y_adj, w_adj, h_adj) device, roi_o, hierarchy3, kept_mask, obj_area = roi_objects( img, 'partial', roi1, roi_hierarchy, id_objects, obj_hierarchy, device, debug) device, obj, mask = object_composition(img, roi_o, hierarchy3, device, debug) cv2.drawContours(ori_img, roi_o, -1, (0, 255, 0), -1, lineType=8, hierarchy=hierarchy3) m = cv2.moments(mask, binaryImage=True) area = m['m00'] center, axes, angle = cv2.fitEllipse(obj) major_axis = np.argmax(axes) minor_axis = 1 - major_axis major_axis_length = axes[major_axis] minor_axis_length = axes[minor_axis] eccentricity = np.sqrt(1 - (axes[minor_axis] / axes[major_axis])**2) else: fatal_error( 'thresh_channel and thresh must be defined in detect mode') else: fatal_error("marker must be either in 'detect' or 'define' mode") analysis_images = [] if filename: out_file = str(filename[0:-4]) + '_sizemarker.jpg' print_image(ori_img, out_file) analysis_images.append(['IMAGE', 'marker', out_file]) if debug is 'print': print_image(ori_img, (str(device) + '_marker_shape.png')) elif debug is 'plot': plot_image(ori_img) marker_header = ('HEADER_MARKER', 'marker_area', 'marker_major_axis_length', 'marker_minor_axis_length', 'marker_eccentricity') marker_data = ('MARKER_DATA', area, major_axis_length, minor_axis_length, eccentricity) return device, marker_header, marker_data, analysis_images
def main(): # Get options args = options() debug = args.debug # Read image img, path, filename = pcv.readimage(args.image) # Pipeline step device = 0 device, img1 = pcv.white_balance(device, img, debug, roi=(1000, 1000, 500, 500)) device, a = pcv.rgb2gray_lab(img1, 'a', device, debug) device, img_binary = pcv.binary_threshold(a, 116, 255, 'dark', device, debug) mask = np.copy(img_binary) device, fill_image = pcv.fill(img_binary, mask, 300, device, debug) device, id_objects, obj_hierarchy = pcv.find_objects(img1, fill_image, device, debug) device, roi, roi_hierarchy = pcv.define_roi(img1, 'rectangle', device, None, 'default', debug, True, 1800, 1600, -1500, -500) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects(img1, 'partial', roi, roi_hierarchy, id_objects, obj_hierarchy, device, debug) outfile = os.path.join(args.outdir, filename) device, color_header, color_data, color_img = pcv.analyze_color(img1, img1, kept_mask, 256, device, debug, None, 'v', 'img', 300, outfile) device, masked = pcv.apply_mask(img1, kept_mask, 'white', device, debug) device, dilated = pcv.dilate(kept_mask, 10, 2, device, debug) device, plant_objects, plant_hierarchy = pcv.find_objects(img1, dilated, device, debug) img_copy = np.copy(img1) color = [(255, 0, 255), (0, 255, 0), (66, 134, 244), (255, 255, 0)] for i in range(0, len(plant_objects)): if len(plant_objects[i]) < 100: pass else: background = np.zeros((np.shape(img1)), np.uint8) cv2.drawContours(background, plant_objects, i, (255, 255, 255), -1, lineType=8, hierarchy=plant_hierarchy) device, grayimg = pcv.rgb2gray(background, device, debug) device, masked1 = pcv.apply_mask(masked, grayimg, 'white', device, debug) device, a1 = pcv.rgb2gray_lab(masked1, 'a', device, debug) device, img_binary1 = pcv.binary_threshold(a1, 116, 255, 'dark', device, debug) device, single_object, single_hierarchy = pcv.find_objects(masked1, img_binary1, device, debug) device, obj, mask = pcv.object_composition(img1, single_object, single_hierarchy, device, debug) device, shape_header, shape_data, shape_img = pcv.analyze_object(img, "img", obj, mask, device, debug) cv2.drawContours(img_copy, plant_objects, i, color[i], -1, lineType=8, hierarchy=plant_hierarchy) plantsize = "Plant matching this color is " + str(shape_data[1]) + " pixels large" cv2.putText(img_copy, plantsize, (500, (i + 1) * 300), cv2.FONT_HERSHEY_SIMPLEX, 5, color[i], 10) pcv.print_image(img_copy, os.path.join(args.outdir, "arabidopsis-out_shapes.jpg"))
debug="print") #plantcv model output mask_image_plant, path, filename = pcv.readimage( '1_naive_bayes_Plant_mask.jpg') ############################################ ###### Perform Calculations ########## ############################################ # combine leaf and labels mask_image_label, path, filename = pcv.readimage( '1_naive_bayes_labels_mask.jpg') mask_image = mask_image_plant + mask_image_label device, mask_image = pcv.rgb2gray_lab(mask_image, 'l', device) #clean the mask up device, img_binary = pcv.binary_threshold(mask_image, 50, 255, 'light', device) pcv.print_image(img_binary, 'img_binary.tif') device, blur_img = pcv.erode( img_binary, 3, 1, device, debug='print' ) # Erode to remove soil and Dilate so that you don't lose leaves (just in case) mask = np.copy(blur_img) device, fill_image = pcv.fill(blur_img, mask, 100, device) pcv.print_image(fill_image, 'fill_image.tif') device, binary_image = pcv.median_blur(fill_image, 1, device) pcv.print_image(binary_image, 'binary_image.tif') device, masked_image = device, dilate_image = pcv.dilate( fill_image, 3, 3, device) ############################################ ########### Create Output #############
def analyze_NIR_intensity(img, rgbimg, mask, bins, device, histplot=False, debug=None, filename=False): """This function calculates the intensity of each pixel associated with the plant and writes the values out to a file. It can also print out a histogram plot of pixel intensity and a pseudocolor image of the plant. Inputs: img = input image original NIR image rgbimg = RGB NIR image mask = mask made from selected contours bins = number of classes to divide spectrum into device = device number. Used to count steps in the pipeline histplot = if True plots histogram of intensity values debug = None, print, or plot. Print = save to file, Plot = print to screen. filename = False or image name. If defined print image Returns: device = device number hist_header = NIR histogram data table headers hist_data = NIR histogram data table values analysis_img = output image :param img: numpy array :param rgbimg: numpy array :param mask: numpy array :param bins: int :param device: int :param histplot: bool :param debug: str :param filename: str :return device: int :return hist_header: list :return hist_data: list :return analysis_img: str """ device += 1 # apply plant shaped mask to image device, mask1 = binary_threshold(mask, 0, 255, 'light', device, None) mask1 = (mask1 / 255) masked = np.multiply(img, mask1) # calculate histogram if img.dtype == 'uint16': maxval = 65536 else: maxval = 256 hist_nir, hist_bins = np.histogram(masked, bins, (1, maxval), False, None, None) hist_bins1 = hist_bins[:-1] hist_bins2 = [l for l in hist_bins1] hist_nir1 = [l for l in hist_nir] # make hist percentage for plotting pixels = cv2.countNonZero(mask1) hist_percent = (hist_nir / float(pixels)) * 100 # report histogram data hist_header = [ 'HEADER_HISTOGRAM', 'bin-number', 'bin-values', 'nir' ] hist_data = [ 'HISTOGRAM_DATA', bins, hist_bins2, hist_nir1 ] analysis_img = [] # make mask to select the background mask_inv = cv2.bitwise_not(mask) img_back = cv2.bitwise_and(rgbimg, rgbimg, mask=mask_inv) img_back1 = cv2.applyColorMap(img_back, colormap=1) # mask the background and color the plant with color scheme 'jet' cplant = cv2.applyColorMap(rgbimg, colormap=2) device, masked1 = apply_mask(cplant, mask, 'black', device, debug=None) cplant_back = cv2.add(masked1, img_back1) if filename: path = os.path.dirname(filename) fig_name = 'NIR_pseudocolor_colorbar.svg' if not os.path.isfile(path + '/' + fig_name): plot_colorbar(path, fig_name, bins) fig_name_pseudo = (str(filename[0:-4]) + '_nir_pseudo_col.jpg') print_image(cplant_back, fig_name_pseudo) analysis_img.append(['IMAGE', 'pseudo', fig_name_pseudo]) if debug is not None: if debug == "print": print_image(masked1, (str(device) + "_nir_pseudo_plant.jpg")) print_image(cplant_back, (str(device) + "_nir_pseudo_plant_back.jpg")) if debug == "plot": plot_image(masked1) plot_image(cplant_back) if histplot is True: import matplotlib matplotlib.use('Agg', warn=False) from matplotlib import pyplot as plt # plot hist percent plt.plot(hist_percent, color='green', label='Signal Intensity') plt.xlim([0, (bins - 1)]) plt.xlabel(('Grayscale pixel intensity (0-' + str(bins) + ")")) plt.ylabel('Proportion of pixels (%)') if filename: fig_name_hist = (str(filename[0:-4]) + '_nir_hist.svg') plt.savefig(fig_name_hist) analysis_img.append(['IMAGE', 'hist', fig_name_hist]) if debug == "print": plt.savefig((str(device) + "_nir_histogram.png")) if debug == "plot": plt.figure() plt.clf() return device, hist_header, hist_data, analysis_img
def read_image_obsolete(self, imagearray): """***Do Not Use***Translate the picture of the dots into a tray number assignment.""" ###Preprocessing & Object Finding Steps device, img1gray = pcv.rgb2gray(imagearray, 0) device, img_binary = pcv.binary_threshold(img1gray, 1, 255, "light", 0) device, id_objects, obj_hierarchy = pcv.find_objects( imagearray, img_binary, 0) device, roi, roi_hierarchy = pcv.define_roi(imagearray, shape="rectangle", device=device, roi_input="default", adjust=False, x_adj=600, y_adj=600, w_adj=1200, h_adj=1200) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( imagearray, "partial", roi, roi_hierarchy, id_objects, obj_hierarchy, device) device, clusters_i, contours, obj_hierarchy = pcv.cluster_contours( device=device, img=imagearray, roi_objects=roi_objects, roi_obj_hierarchy=roi_obj_hierarchy, nrow=1, ncol=int(3)) out = "/Users/gghosal/Desktop/gaurav/res" device, output_path = pcv.cluster_contour_splitimg( device=device, img=imagearray, grouped_contour_indexes=clusters_i, contours=contours, hierarchy=obj_hierarchy, outdir=out) obj_hierarchy = obj_hierarchy[0] centroids = list() totalcontours = list() #print(len(contours)) for clusters1 in clusters_i: totalcontour = contours[clusters1[0]] for j in clusters1[1:]: totalcontour = np.concatenate((contours[j], totalcontour), axis=0) totalcontours.append(totalcontour) mmt = cv2.moments(totalcontour) ycoords = int(mmt['m10'] / mmt['m00']) xcoords = int(mmt['m01'] / mmt['m00']) #cv2.circle(img1, (ycoords, xcoords), 3, (255, 0, 0), 3) centroids.append(tuple([ycoords, xcoords])) count11 = 0 for clusters1 in clusters_i: for contourtocheck in clusters1: if not obj_hierarchy[contourtocheck][2] == -1: if not cv2.contourArea( clusters_i[obj_hierarchy[contourtocheck][2]]) >= 5: obj_hierarchy[contourtocheck][2] = -1 dotlist = list() for foundcontour in clusters_i: hierarchycontours = [obj_hierarchy[j][2] for j in foundcontour] if not all([bool(j == -1) for j in hierarchycontours]): dotlist.append(True) else: dotlist.append(False) colors = self.read_colors(out) for pnr in range(3): dot_characteristics.append(tuple((colors[pnr], dotlist[pnr]))) try: return self.translator[self.translate(dot_characteristics)] except: return "Error"
def read_image2(self, imageread): """This is the current implementation for finding and reading the dot codes. """ os.chdir('/Users/gghosal/Desktop/gaurav/res/') self.centers = list() for i in self.listdir_nohidden('/Users/gghosal/Desktop/gaurav/res/'): os.remove(i) #color_recognition_dict={'red':0, "lightblue":98, "darkblue":120, "pink":175, "purple":140} img1 = imageread device, img1gray = pcv.rgb2gray(img1, 0) img1hsv = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV) dev, img_binary = pcv.binary_threshold(img1gray, 1, 255, 'light', 0) device, id_objects, obj_hierarchy = pcv.find_objects( img1, img_binary, 0) device, roi, roi_hierarchy = pcv.define_roi(img1, shape="rectangle", device=device, roi_input="default", adjust=False, x_adj=600, y_adj=600, w_adj=1200, h_adj=1200) device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img1, "partial", roi, roi_hierarchy, id_objects, obj_hierarchy, device) device, clusters_i, contours, obj_hierarchy = pcv.cluster_contours( device=device, img=img1, roi_objects=roi_objects, roi_obj_hierarchy=roi_obj_hierarchy, nrow=1, ncol=int(3)) out = "/Users/gghosal/Desktop/gaurav/res" device, output_path = pcv.cluster_contour_splitimg( device=device, img=img1, grouped_contour_indexes=clusters_i, contours=contours, hierarchy=obj_hierarchy, outdir=out) obj_hierarchy = obj_hierarchy[0] dotQ = list() centroids = list() totalcontours = list() for clusters1 in clusters_i: totalcontour = contours[clusters1[0]] for j in clusters1[1:]: totalcontour = np.concatenate((contours[j], totalcontour), axis=0) totalcontours.append(totalcontour) mmt = cv2.moments(totalcontour) ycoords = int(mmt['m10'] / mmt['m00']) xcoords = int(mmt['m01'] / mmt['m00']) self.centers.append(tuple([ycoords, xcoords])) centroids.append(tuple([xcoords, ycoords])) count11 = 0 dot_cleaned = apply_brightness_contrast(imageread, brightness=0, contrast=49) dot_cleaned_grey = cv2.cvtColor(dot_cleaned, cv2.COLOR_RGB2HSV) dot_cleaned_thresh = cv2.inRange(dot_cleaned_grey, np.array([0, 0, 150]), np.array([255, 255, 255])) dot_cleaned = cv2.bitwise_and(dot_cleaned, dot_cleaned, mask=dot_cleaned_thresh) dot_kernel = np.ones((7, 7), np.uint8) dotQ = self.read_dot3(dot_cleaned) os.chdir(out) colors = list() dot_characteristics = list() for i in self.listdir_nohidden(out): #print(i) if self.masked(i): mask = cv2.imread(i, 0) unmasked = cv2.imread(i[0:-5]) width = mask.shape[0] length = mask.shape[1] color_averagelist = list() masked_img1hsv = cv2.bitwise_and(img1hsv, img1hsv, mask=mask) color_averagelist = cv2.split(masked_img1hsv)[0] color_averagelist = np.reshape(color_averagelist, (color_averagelist.shape[0] * color_averagelist.shape[1], )) color_averagelist = color_averagelist[np.flatnonzero( color_averagelist)] color_avg = statistics.mode(color_averagelist) resultsdict = dict() for color in self.colordefinitions: resultsdict[color] = abs(self.colordefinitions[color] - color_avg) color = min(resultsdict, key=lambda x: resultsdict[x]) colors.append(color) for pnr in range(3): dot_characteristics.append(tuple((colors[pnr], dotQ[pnr]))) try: return self.translator.get(self.translate(dot_characteristics), self.translate(dot_characteristics)) except Exception as e: pass
def main(): # Get options args = options() # Read image img, path, filename = pcv.readimage(args.image) debug = args.debug # Pipeline step device = 0 # Step 1: Check if this is a night image, for some of these datasets images were captured # at night, even if nothing is visible. To make sure that images are not taken at # night we check that the image isn't mostly dark (0=black, 255=white). # if it is a night image it throws a fatal error and stops the pipeline. if np.average(img) < 50: pcv.fatal_error("Night Image") else: pass # Step 2: Normalize the white color so you can later # compare color between images. # Inputs: # device = device number. Used to count steps in the workflow # img = image object, RGB colorspace # debug = None, print, or plot. Print = save to file, Plot = print to screen. # roi = region for white reference, if none uses the whole image, # otherwise (x position, y position, box width, box height) #white balance image based on white toughspot device, img1 = pcv.white_balance(device, img, debug, roi=white_balance_roi) # img1 = img # Step 3: Rotate the image # device, rotate_img = pcv.rotate(img1, -1, device, debug) #Step 4: Shift image. This step is important for clustering later on. # For this image it also allows you to push the green raspberry pi camera # out of the image. This step might not be necessary for all images. # The resulting image is the same size as the original. # Input: # img = image object # device = device number. Used to count steps in the workflow # number = integer, number of pixels to move image # side = direction to move from "top", "bottom", "right","left" # debug = None, print, or plot. Print = save to file, Plot = print to screen. # device, shift1 = pcv.shift_img(img1, device, 300, 'top', debug) # img1 = shift1 # STEP 5: Convert image from RGB colorspace to LAB colorspace # Keep only the green-magenta channel (grayscale) # Inputs: # img = image object, RGB colorspace # channel = color subchannel (l = lightness, a = green-magenta , b = blue-yellow) # device = device number. Used to count steps in the workflow # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, a = pcv.rgb2gray_lab(img1, 'a', device, debug) # STEP 6: Set a binary threshold on the Saturation channel image # Inputs: # img = img object, grayscale # threshold = threshold value (0-255) # maxValue = value to apply above threshold (usually 255 = white) # object_type = light or dark # - If object is light then standard thresholding is done # - If object is dark then inverse thresholding is done # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, img_binary = pcv.binary_threshold(a, darkness_threshold, 255, 'dark', device, debug) # ^ # | # adjust this value # STEP 7: Fill in small objects (speckles) # Inputs: # img = image object, grayscale. img will be returned after filling # mask = image object, grayscale. This image will be used to identify contours # size = minimum object area size in pixels (integer) # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. mask = np.copy(img_binary) device, fill_image = pcv.fill(img_binary, mask, minimum_object_area_pixels, device, debug) # ^ # | # adjust this value # STEP 8: Dilate so that you don't lose leaves (just in case) # Inputs: # img = input image # kernel = integer # i = interations, i.e. number of consecutive filtering passes # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, dilated = pcv.dilate(fill_image, 1, 1, device, debug) # STEP 9: Find objects (contours: black-white boundaries) # Inputs: # img = image that the objects will be overlayed # mask = what is used for object detection # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, id_objects, obj_hierarchy = pcv.find_objects( img1, dilated, device, debug) # STEP 10: Define region of interest (ROI) # Inputs: # img = img to overlay roi # roi = default (None) or user input ROI image, object area should be white and background should be black, # has not been optimized for more than one ROI # roi_input = type of file roi_base is, either 'binary', 'rgb', or 'default' (no ROI inputted) # shape = desired shape of final roi, either 'rectangle' or 'circle', if user inputs rectangular roi but chooses # 'circle' for shape then a circle is fitted around rectangular roi (and vice versa) # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. # adjust = either 'True' or 'False', if 'True' allows user to adjust ROI # x_adj = adjust center along x axis # y_adj = adjust center along y axis # w_adj = adjust width # h_adj = adjust height # x=0, y=560, h=4040-560, w=3456 roi_contour, roi_hierarchy = pcv.roi.rectangle(**total_region_of_interest, img=img1) # device, roi, roi_hierarchy = pcv.define_roi(img1, 'rectangle', device, None, 'default', debug, False, # 0, 0, 0, 0) # ^ ^ # |________________| # adjust these four values # STEP 11: Keep objects that overlap with the ROI # Inputs: # img = img to display kept objects # roi_type = 'cutto' or 'partial' (for partially inside) # roi_contour = contour of roi, output from "View and Ajust ROI" function # roi_hierarchy = contour of roi, output from "View and Ajust ROI" function # object_contour = contours of objects, output from "Identifying Objects" fuction # obj_hierarchy = hierarchy of objects, output from "Identifying Objects" fuction # device = device number. Used to count steps in the pipeline # debug = None, print, or plot. Print = save to file, Plot = print to screen. device, roi_objects, roi_obj_hierarchy, kept_mask, obj_area = pcv.roi_objects( img1, 'partial', roi_contour, roi_hierarchy, id_objects, obj_hierarchy, device, debug) # print(obj_area) #Step 12: This function take a image with multiple contours and # clusters them based on user input of rows and columns #Inputs: # img - An RGB image array # roi_objects - object contours in an image that are needed to be clustered. # nrow - number of rows to cluster (this should be the approximate number of desired rows in the entire image (even if there isn't a literal row of plants) # ncol - number of columns to cluster (this should be the approximate number of desired columns in the entire image (even if there isn't a literal row of plants) # file - output of filename from read_image function # filenames - input txt file with list of filenames in order from top to bottom left to right # debug - print debugging images device, clusters_i, contours = pcv.cluster_contours( device, img1, roi_objects, expected_number_of_rows, expected_number_of_columns, debug) # print(contours) #Step 13:This function takes clustered contours and splits them into multiple images, #also does a check to make sure that the number of inputted filenames matches the number #of clustered contours. If no filenames are given then the objects are just numbered #Inputs: # img - ideally a masked RGB image. # grouped_contour_indexes - output of cluster_contours, indexes of clusters of contours # contours - contours to cluster, output of cluster_contours # filenames - input txt file with list of filenames in order from top to bottom left to right (likely list of genotypes) # debug - print debugging images out = args.outdir names = args.names device, output_path = pcv.cluster_contour_splitimg(device, img1, clusters_i, contours, out, file=filename, filenames=names, debug=debug)