diff --git a/simrdwn/core/simrdwn.py b/simrdwn/core/simrdwn.py index ea055c3..6231f73 100755 --- a/simrdwn/core/simrdwn.py +++ b/simrdwn/core/simrdwn.py @@ -205,7 +205,8 @@ def update_args(args): args.test_add_geo_coords = bool(args.test_add_geo_coords) # set cuda values - if args.gpu >= 0: + # if args.gpu >= 0: + if args.gpu != "-1": args.use_GPU, args.use_CUDNN = 1, 1 else: args.use_GPU, args.use_CUDNN = 0, 0 @@ -661,6 +662,7 @@ def yolt_command(framework='yolt2', else: gpu_cmd = '-i ' + str(gpu) # gpu_cmd = '-i ' + str(3-args.gpu) # originally, numbers were reversed + ngpus = len(gpu.split(',')) ########################## # SET VARIABLES ACCORDING TO MODE (SET UNNECCESSARY VALUES TO 0 OR NULL) @@ -713,6 +715,7 @@ def yolt_command(framework='yolt2', str(nbands), yolt_loss_file, str(min_retain_prob), + str(ngpus), suffix ] @@ -1732,8 +1735,9 @@ def main(): help="object detection framework [yolt2, 'yolt3', ssd, faster_rcnn]") parser.add_argument('--mode', type=str, default='test', help="[compile, test, train, test]") - parser.add_argument('--gpu', type=int, default=0, - help="GPU number, set < 0 to turn off GPU support") + parser.add_argument('--gpu', type=str, default="0", + help="GPU number, set < 0 to turn off GPU support " \ + "to use multiple, use '0,1'") parser.add_argument('--single_gpu_machine', type=int, default=0, help="Switch to use a machine with just one gpu") parser.add_argument('--nbands', type=int, default=3, diff --git a/simrdwn/data_prep/parse_shapefile.py b/simrdwn/data_prep/parse_shapefile.py new file mode 100644 index 0000000..6651d1d --- /dev/null +++ b/simrdwn/data_prep/parse_shapefile.py @@ -0,0 +1,775 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +""" +Created on Mon Aug 14 14:04:00 2017 + +@author: avanetten +""" + +import geopandas as gpd +import numpy as np +import sys +import os +import shapely +import rasterio +import affine +import gdal, osr, ogr +import cv2 +import argparse +import shutil + + +############################################################################### +def geomGeo2geomPixel(geom, affineObject=[], input_raster='', gdal_geomTransform=[]): + '''From SpaceNet Utilities''' + + # This function transforms a shapely geometry in geospatial coordinates into pixel coordinates + # geom must be shapely geometry + # affineObject = rasterio.open(input_raster).affine + + gdal_geomTransform = gdal.Open(input_raster).GetGeoTransform() + # input_raster is path to raster to gather georectifcation information + if not affineObject: + if input_raster != '': + affineObject = rasterio.open(input_raster).affine + else: + affineObject = affine.Affine.from_gdal(gdal_geomTransform) + + affineObjectInv = ~affineObject + + geomTransform = shapely.affinity.affine_transform(geom, + [affineObjectInv.a, + affineObjectInv.b, + affineObjectInv.d, + affineObjectInv.e, + affineObjectInv.xoff, + affineObjectInv.yoff] + ) + + return geomTransform + + +############################################################################### +def geomPixel2geomGeo(geom, affineObject=[], input_raster='', gdal_geomTransform=[]): + ''' + From SpaceNet Utilities + # This function transforms a shapely geometry in pixel coordinates into geospatial coordinates + # geom must be shapely geometry + # affineObject = rasterio.open(input_raster).affine + # gdal_geomTransform = gdal.Open(input_raster).GetGeoTransform() + # input_raster is path to raster to gather georectifcation information + ''' + gdal_geomTransform = gdal.Open(input_raster).GetGeoTransform() + if not affineObject: + if input_raster != '': + affineObject = rasterio.open(input_raster).affine + else: + affineObject = affine.Affine.from_gdal(gdal_geomTransform) + + +############################################################################### +def latlon2pixel(lat, lon, input_raster='', targetsr='', geom_transform=''): + # type: (object, object, object, object, object) -> object + '''from spacenet geotools''' + + sourcesr = osr.SpatialReference() + sourcesr.ImportFromEPSG(4326) + + geom = ogr.Geometry(ogr.wkbPoint) + geom.AddPoint(lon, lat) + + if targetsr == '': + src_raster = gdal.Open(input_raster) + targetsr = osr.SpatialReference() + targetsr.ImportFromWkt(src_raster.GetProjectionRef()) + coord_trans = osr.CoordinateTransformation(sourcesr, targetsr) + if geom_transform == '': + src_raster = gdal.Open(input_raster) + transform = src_raster.GetGeoTransform() + else: + transform = geom_transform + + x_origin = transform[0] + # print(x_origin) + y_origin = transform[3] + # print(y_origin) + pixel_width = transform[1] + # print(pixel_width) + pixel_height = transform[5] + # print(pixel_height) + geom.Transform(coord_trans) + # print(geom.GetPoint()) + x_pix = (geom.GetPoint()[0] - x_origin) / pixel_width + y_pix = (geom.GetPoint()[1] - y_origin) / pixel_height + + return (x_pix, y_pix) + + +############################################################################### +def transform_crs(input_raster): + + '''If crs of input_raster is not epsg:4326, transform it to be so. + Copy original file to: os.path.join(dirname + '/orig', basename) + ''' + + truth_dir = os.path.dirname(input_raster) + basename = os.path.basename(input_raster) + + #input_raster = os.path.join(truth_dir, input_raster_part) + + orig_dir = os.path.join(truth_dir, 'orig') + if not os.path.exists(orig_dir): + os.mkdir(orig_dir) + + if input_raster.endswith('_new.tif'): + return + + crs = rasterio.open(input_raster).crs + + # check if the crs is not epsg:4326 + if crs.data['init'] == u'epsg:4326': + return + + else: + # copy file to orig folder, if it doesn't already exist + orig_dest = os.path.join(orig_dir, basename) + if not os.path.exists(orig_dest): + print ("input_raster:", input_raster) + print (" crs:", crs) + print (" copy", input_raster, "to", orig_dest) + shutil.copy(input_raster, orig_dest) + + # transform + output_raster = input_raster.split('.')[0] + '_new.tif' + cmd = 'gdalwarp -t_srs "EPSG:4326" ' + orig_dest + ' ' + output_raster + os.system(cmd) + + # move files around + os.remove(input_raster) + shutil.copy(output_raster, input_raster) + return + + + +############################################################################### +def get_gdf_pix_coords(shp_file, im_file, category='', + max_aspect_ratio=3, line_padding=0.1, + enforce_rects=False, + verbose=False): + '''Get pixel coords of shape file + If the labels are single linestrings, infer a bounding box + max_aspect_ratio prevents a window of zero width or height + line_padding adds a buffer to the boundong box if labels are lines''' + + df_shp = gpd.read_file(shp_file) + init_proj = df_shp.crs + + if len(category) == 0: + category = shp_file.split('.')[0].split('_')[-1] + + if verbose: + print ("\nGet gdf for shape file:", shp_file) + print ("init_proj:", init_proj) + print ("category:", category) + + # get transform data (if using latlton2pixel) + #src_raster = gdal.Open(im_file) + #transform = src_raster.GetGeoTransform() + #targetsr = osr.SpatialReference() + #targetsr.ImportFromWkt(src_raster.GetProjectionRef()) + + pix_geom_list = [] + pix_geom_poly_list = [] + pix_coords = [] + bad_idxs = [] + x0_list, x1_list, y0_list, y1_list = [], [], [], [] + + + #for obj in df_shp['geometry'].values: + for index, row in df_shp.iterrows(): + + obj = row['geometry'] + + # get coords + #init_coords = list(obj.coords) + + ## with latlon2pixel + #print "init coords:", init_coords + #for i,c in enumerate(init_coords): + # print i, "init_coords:", c + # (lon, lat) = c + # x,y = latlon2pixel(lat, lon, input_raster='', targetsr=targetsr, + # geom_transform=transform) + # print "x,y:", x,y + + # all at once + try: + pix = geomGeo2geomPixel(obj, rasterio.open(im_file).affine, im_file) + except: + print (index, "bad row:", row) + bad_idxs.append(index) + #pix_geom_list.append([0]) + #pix_geom_poly_list.append([0]) + #pix_coords.append([0]) + continue + + if verbose: + print ("pix.geom_type:", pix.geom_type) + + # if pix is a linestring with only 2 points, + # lets make sure that it is transformed into a bounding box + if len(np.array(pix)) == 2: + if verbose: + print ("Inferring bounding box from line...") + coords = np.array(pix) + + # get x and y coords + x, y = coords.T + # get midpoints of line + m_x, m_y = np.mean(x), np.mean(y) + dx0 = np.abs(x[1] - x[0]) + dy0 = np.abs(y[1] - y[0]) + # check aspect ratio + if dx0 > max_aspect_ratio * dy0: + dx = dx0 + dy = dx0 / max_aspect_ratio + elif dy0 > max_aspect_ratio * dx0: + dy = dy0 + dx = dy0 / max_aspect_ratio + else: + dx, dy = dx0, dy0 + # add padding + dx *= (1 + line_padding) + dy *= (1 + line_padding) + # create bounding boxes + x0, x1 = m_x - dx/2, m_x + dx/2 + y0, y1 = m_y - dy/2, m_y + dy/2 + out_coords = [[x0, y0], [x0, y1], [x1, y1], [x1, y0]] + points = [shapely.geometry.Point(coord) for coord in out_coords] + pix_poly = shapely.geometry.Polygon([[p.x, p.y] for p in points]) + + else: + pix_poly = shapely.geometry.Polygon(pix) + + + # convert to bounding box, if desired + if enforce_rects: + (x0_tmp, y0_tmp, x1_tmp, y1_tmp) = pix_poly.bounds + pix_poly = shapely.geometry.box(x0_tmp, y0_tmp, x1_tmp, + y1_tmp, ccw=True) + + minx, miny, maxx, maxy = pix_poly.bounds + x0_list.append(minx) + x1_list.append(maxx) + y0_list.append(miny) + y1_list.append(maxy) + pix_geom_list.append(pix) + pix_geom_poly_list.append(pix_poly) + pix_coords.append(list(pix.coords)) + + # drop bad indexs + df_shp = df_shp.drop(df_shp.index[bad_idxs]) + + if verbose: + print ("len df_shp:", len(df_shp)) + print ("len pix_geom_list:", len(pix_geom_list)) + + df_shp['geometry_pixel'] = pix_geom_list + df_shp['geometry_poly_pixel'] = pix_geom_poly_list + df_shp['xmin'] = x0_list + df_shp['xmax'] = x1_list + df_shp['ymin'] = y0_list + df_shp['ymax'] = y1_list + df_shp['shp_file'] = shp_file + df_shp['Category'] = category + df_shp['Image_Path'] = im_file + df_shp['Image_Root'] = im_file.split('/')[-1] + + return df_shp, pix_coords + + +############################################################################### +def win_jitter(window_size, jitter_frac=0.1): + '''get x and y jitter''' + val = np.rint(jitter_frac * window_size) + dx = np.random.randint(-val, val) + dy = np.random.randint(-val, val) + + return dx, dy + + +############################################################################### +def get_window_geoms(df, window_size=416, jitter_frac=0.2, verbose=False): + '''Iterate through dataframe and get the window cutouts centered on each + object, modulu some jitter''' + + geom_windows = [] + for index, row in df.iterrows(): + print ("\n", index, row['Category']) + # get coords + geom_pix = row['geometry_poly_pixel'] + #pix_coords = list(geom_pix.coords) + bounds = geom_pix.bounds + area = geom_pix.area + (minx, miny, maxx, maxy) = bounds + dx, dy = maxx-minx, maxy-miny + if verbose: + print ("bounds:", bounds ) + print ("dx, dy:", dx, dy ) + print ("area:", area ) + + # get centroid + centroid = geom_pix.centroid + #print "centroid:", centroid + cx_tmp, cy_tmp = list(centroid.coords)[0] + cx, cy = np.rint(cx_tmp), np.rint(cy_tmp) + + # get window coords, jitter, and shapely geometry for window + jx, jy = win_jitter(window_size, jitter_frac=jitter_frac) + x0 = cx - window_size/2 + jx + y0 = cy - window_size/2 + jy + x1 = x0 + window_size + y1 = y0 + window_size + win_p1 = shapely.geometry.Point(x0, y0) + win_p2 = shapely.geometry.Point(x1, y0) + win_p3 = shapely.geometry.Point(x1, y1) + win_p4 = shapely.geometry.Point(x0, y1) + pointList = [win_p1, win_p2, win_p3, win_p4, win_p1] + geom_window = shapely.geometry.Polygon([[p.x, p.y] for p in pointList]) + if verbose: + print ("geom_window.bounds", geom_window.bounds ) + geom_windows.append(geom_window) + + return geom_windows + + +############################################################################### +def get_objs_in_window(df_, geom_window, min_obj_frac=0.7, + use_box_geom=True, verbose=False): + '''Find all objects in the window''' + + (minx_win, miny_win, maxx_win, maxy_win) = geom_window.bounds + if verbose: + print ("geom_window.bounds:", geom_window.bounds) + + obj_list = [] + for index_nest, row_nest in df_.iterrows(): + cat_nest = row_nest['Category'] + geom_pix_nest_tmp = row_nest['geometry_poly_pixel'] + + # if use_box_geom, turn the shapefile object geom into a bounding box + if use_box_geom: + (x0, y0, x1, y1) = geom_pix_nest_tmp.bounds + geom_pix_nest = shapely.geometry.box(x0, y0, x1, y1, ccw=True) + else: + geom_pix_nest = geom_pix_nest_tmp + + #pix_coords = list(geom_pix.coords) + #bounds_nest = geom_pix_nest.bounds + area_nest = geom_pix_nest.area + # sometimes we get an invalid geometry, not sure why + try: + intersect_geom = geom_pix_nest.intersection(geom_window) + except: + # create a buffer around the exterior + geom_pix_nest = geom_pix_nest.buffer(0) + intersect_geom = geom_pix_nest.intersection(geom_window) + print ("Had to update geom_pix_nest:", geom_pix_nest.bounds ) + + intersect_bounds = intersect_geom.bounds + intersect_area = intersect_geom.area + intersect_frac = intersect_area / area_nest + + + # skip if object not in window, else add to window + if intersect_frac < min_obj_frac: + continue + else: + # get window coords + (minx_nest, miny_nest, maxx_nest, maxy_nest) = intersect_bounds + dx_nest, dy_nest = maxx_nest - minx_nest, maxy_nest - miny_nest + x0_obj, y0_obj = minx_nest - minx_win, miny_nest - miny_win + x1_obj, y1_obj = x0_obj + dx_nest, y0_obj + dy_nest + + x0_obj, y0_obj, x1_obj, y1_obj = np.rint(x0_obj), np.rint(y0_obj),\ + np.rint(x1_obj), np.rint(y1_obj) + obj_list.append([index_nest, cat_nest, x0_obj, y0_obj, x1_obj, + y1_obj]) + if verbose: + print (" ", index_nest, "geom_obj.bounds:", geom_pix_nest.bounds ) + print (" intesect area:", intersect_area ) + print (" obj area:", area_nest ) + print (" intersect_frac:", intersect_frac ) + print (" intersect_bounds:", intersect_bounds ) + print (" category:", cat_nest ) + + return obj_list + + +############################################################################### +def get_image_window(im, window_geom): + '''Get sub-window in image''' + + bounds_int = [int(itmp) for itmp in window_geom.bounds] + (minx_win, miny_win, maxx_win, maxy_win) = bounds_int + window = im[miny_win:maxy_win, minx_win:maxx_win] + return window + + +############################################################################### +def plot_obj_list(window, obj_list, color_dic, thickness=2, + show_plot=False, outfile=''): + '''Plot the cutout, and the object bounds''' + + print ("window.shape:", window.shape ) + + for row in obj_list: + [index_nest, cat_nest, x0_obj, y0_obj, x1_obj, y1_obj] = row + color = color_dic[cat_nest] + + cv2.rectangle(window, (int(x0_obj), int(y0_obj)), + (int(x1_obj), int(y1_obj)), + (color), thickness) + + if show_plot: + cv2.imshow(str(index_nest), window) + cv2.waitKey(0) + + if outfile: + cv2.imwrite(outfile, window) + + +############################################################################### +def plot_obj_list_v0(im, window_geom, obj_list, color_dic, thickness=2, + show_plot=False, outfile=''): + '''Plot the cutout, and the object bounds''' + + bounds_int = [int(itmp) for itmp in window_geom.bounds] + (minx_win, miny_win, maxx_win, maxy_win) = bounds_int + + + window = im[miny_win:maxy_win, minx_win:maxx_win] + #window_c = image0[y:y + sliceHeight, x:x + sliceWidth] + print ("window.shape:", window.shape ) + + for row in obj_list: + [index_nest, cat_nest, x0_obj, y0_obj, x1_obj, y1_obj] = row + color = color_dic[cat_nest] + + cv2.rectangle(window, (int(x0_obj), int(y0_obj)), + (int(x1_obj), int(y1_obj)), + (color), thickness) + + if show_plot: + cv2.imshow(str(index_nest), window) + cv2.waitKey(0) + + if outfile: + cv2.imwrite(outfile, window) + + + + +############################################################################### +############################################################################### +def main(): + + parser = argparse.ArgumentParser() + + parser.add_argument('--indir', default='/Users/avanetten/cosmiq/simrdwn', + type=str, + help='Data directory') + parser.add_argument('--outdir', + default='/Users/avanetten/cosmiq/simrdwn/sweet_sweet_nectar', type=str, + help='Output folder for labels') + parser.add_argument('--im_file', default='pic.tif', type=str, + help='Image file to analyze') + parser.add_argument('--shp_file', default='obj.shp', type=str, + help='Shapefile containing object labels') + parser.add_argument('--window_size', default=416, type=int, + help='Size of window cutouts (assumed to be square)') + parser.add_argument('--jitter_frac', default=0.2, type=float, + help='Jiffer fraction') + parser.add_argument('--min_obj_frac', default=0.7, type=float, + help='Minimum portion of object to include in a subwindow label') + parser.add_argument('--max_plots', default=20, type=int, + help='Maximum number of illustrative plots to create') + parser.add_argument('--max_redundancy', default=10, type=int, + help='By default, we extract a window for each object. For densely' \ + + ' packed objects this means many windows that are nearly identical.'\ + + ' max_reduncancy sets the maximum times a given obejct can be seen.'\ + + ' If any object has been seen more that this value, skip the window') + parser.add_argument('--yolt_dir', default='/Users/avanetten/cosmiq/simrdwn', type=str, + help='Location of yolt directory') + parser.add_argument('--overwrite_output', default='True', type=str, + help='If true, overwrite output directory') + parser.add_argument('--augment', default='False', type=str, + help='If true, augment data with rotations and hsv rescalings') + parser.add_argument('--image_extension', default='.png', type=str, + help='Extension for output images, set to "" to use input extension') + + args = parser.parse_args() + print ("args:", args ) + + sys.path.extend([args.yolt_dir]) + import convert + import yolt_data_prep_funcs + + verbose = True + plot_thickness = 2 + im_root = args.im_file.split('.')[0] + if len(args.image_extension) == 0: + ext = '.'+ args.im_file.split('.')[-1] + else: + ext = args.image_extension + color_dic = {'airplane': (0, 0, 255), + 'airport:': (0, 140, 255), + 'boat': (255, 0, 0), + 'boat_harbor': (0, 255, 0), + 'car': (125, 125, 0)} + cat_idx_dic = {'airplane': 1, + 'airport:': 2, + 'boat': 3, + 'boat_harbor': 4, + 'car': 5} + +# if args.overwrite_output.upper() == 'TRUE': +# print ("Removing outdir:", args.outdir +# if os.path.exists(args.outdir): +# # lets make sure we don't remove something important on accident +# if len(args.outdir) > len() +# shutil.rmtree(args.outdir) + + outdir_tot = os.path.join(args.outdir, im_root) + outdir_ims = os.path.join(outdir_tot, 'images') + outdir_labels = os.path.join(outdir_tot, 'labels') + outdir_plots = os.path.join(outdir_tot, 'example_label_plots') + outdir_yolt_plots = os.path.join(outdir_tot, 'yolt_plot_bboxes') + train_images_list_file = os.path.join(outdir_tot, 'train_images_list.txt') + for f in [outdir_tot, outdir_ims, outdir_labels]: + if not os.path.exists(f): + os.mkdir(f) + if (args.max_plots > 0): + for f in [outdir_plots, outdir_yolt_plots]: + if not os.path.exists(f): + os.mkdir(f) + + # clean directories + if args.overwrite_output.upper() == 'TRUE': + dirs_clean = [outdir_labels, outdir_ims, outdir_plots, + outdir_yolt_plots] + print ("Cleansing dirs :", dirs_clean ) + for d in dirs_clean: + shutil.rmtree(d) + os.mkdir(d) + + ####################### + # ingest files + #im_file = os.path.join(indir, im_root + '.tif') + im_file = os.path.join(args.indir, args.im_file) + + print ("Reading file:", im_file, "..." ) + if not os.path.exists(im_file): + print (" file DNE..." ) + im = cv2.imread(im_file, 1) # fails on some tiffs + + # sometimes opencv can't read weird tiffs. If so, convert + # gdal_translate -co "COMPRESS=LZW" -co PHOTOMETRIC=rgb in.tif out.tif + # gdalinfo out.tif + + # other ingest options? + #im = tiff.imread(im_file) + #im_pil = Image.open(im_file) + #im_rgb = np.array(im_pil) + #im = cv2.cvtColor(im_rgb, cv2.COLOR_RGB2BGR) + + if verbose: + print ("im_file:", im_file ) + print (" im.shape:", im.shape ) + + # get shape files + #shp_files = glob.glob(os.path.join(indir, im_root + '*.shp')) + shp_files = [os.path.join(args.indir, args.shp_file)] + # create combined dataframe + df = [] + for i,shp_f in enumerate(shp_files): + category = shp_f.split('_')[-1].split('.')[0] + #category = args.category + print ("shape_file:", shp_f ) + print (os.path.exists(shp_f )) + print (" category:", category ) + df_tmp, _ = get_gdf_pix_coords(shp_f, im_file, category) + if i == 0: + df = df_tmp + else: + df = df.append(df_tmp) + df.index = np.arange(len(df)) + + if verbose: + print ("df.columns:", df.columns ) + ####################### + + # get window cutouts centered at each object + window_geoms = get_window_geoms(df, window_size=args.window_size, + jitter_frac=args.jitter_frac, + verbose=verbose) + + idx_count_dic = {} + for idx_tmp in df.index: + idx_count_dic[idx_tmp] = 0 + idx_count_tot_dic = {} + for idx_tmp in df.index: + idx_count_tot_dic[idx_tmp] = 0 + # get objects in each window + win_iter = 0 + for i,window_geom in enumerate(window_geoms): + + (minx_win, miny_win, maxx_win, maxy_win) = window_geom.bounds + + # get window + window = get_image_window(im, window_geom) + h, w = window.shape[:2] + if (h==0) or (w==0): + continue + + # get objects in window + obj_list = get_objs_in_window(df, window_geom, + min_obj_frac=args.min_obj_frac, + verbose=verbose) + if verbose: + print ("\nWindow geom:", window_geom ) + print (" window shape:", window.shape ) + print (" obj_list:", obj_list ) + + if len(obj_list) > 0 : + + # update idx_count_tot_dic + idxs_list = [z[0] for z in obj_list] + for idx_tmp in idxs_list: + idx_count_tot_dic[idx_tmp] += 1 + + # Check idx count dic. If an object has appeared too frequently, + # skip the window + excess = False + for idx_tmp in idxs_list: + if idx_count_dic[idx_tmp] >= args.max_redundancy: + print ("Index", idx_tmp, "seen too frequently, skipping..." ) + excess = True + break + if excess: + continue + + # create yolt images and labels + outroot = im_root + '|x0_' + str(int(minx_win)) + '_y0_' \ + + str(int(miny_win)) + '_dxdy_' \ + + str(int(args.window_size)) + + image_outfile = os.path.join(outdir_ims, outroot + ext) + label_outfile = os.path.join(outdir_labels, outroot + '.txt') + plot_outfile = os.path.join(outdir_plots, outroot + ext) + + if verbose: + print (" Saving window to file..." ) + print (" window.dtype:", window.dtype ) + print (" window.shape:", window.shape ) + # save image + cv2.imwrite(image_outfile, window) + + # get yolt labels + #if verbose: + # print (" Creating yolt labels..." + yolt_coords = [] + for row in obj_list: + [index_nest, cat_nest, x0, y0, x1, y1] = row + cat_idx = cat_idx_dic[cat_nest] + yolt_row = [cat_idx, cat_nest] + list(convert.convert((w,h), [x0,x1,y0,y1])) + yolt_coords.append(yolt_row) + if verbose: + print (" yolt_coords:", yolt_coords ) + + # save labels + txt_outfile = open(label_outfile, "w") + for j, yolt_row in enumerate(yolt_coords): + cls_id = yolt_row[0] + bb = yolt_row[2:] + outstring = str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n' + #print ("outstring:", outstring + txt_outfile.write(outstring) + txt_outfile.close() + + # make plots + if i <= args.max_plots: + if verbose: + print ("obj_list:",obj_list ) + print ("plot outfile:", plot_outfile ) + #im_copy = im.copy() + #plot_obj_list(im_copy, window_geom, obj_list, color_dic, + plot_obj_list(window.copy(), obj_list, color_dic, + thickness=plot_thickness, show_plot=False, + outfile=plot_outfile) + + # update idx_count_dic + for idx_tmp in idxs_list: + idx_count_dic[idx_tmp] += 1 + # update win_iter + win_iter += 1 + + + # augment, if desired + if args.augment.upper() == 'TRUE': + yolt_data_prep_funcs.augment_training_data(outdir_labels, outdir_ims, + hsv_range=[0.5,1.5], + ext=ext, + skip_hsv_transform=False) + + # make sure labels and images are created correctly + print ("\nPlotting yolt training bounding boxes..." ) + print ("outdir_labels:", outdir_labels ) + print ("outdir_ims:", outdir_ims ) + yolt_data_prep_funcs.plot_training_bboxes(outdir_labels, outdir_ims, + ignore_augment=True, + figsize=(10,10), color=(0,0,255), thickness=2, + max_plots=100, sample_label_vis_dir=outdir_yolt_plots, + ext=ext, verbose=verbose, show_plot=False, + specific_labels=[], label_dic=[], output_width=500, + shuffle=True) + + # make training list + list_file = open(train_images_list_file, 'wb') + for f in os.listdir(outdir_ims): + list_file.write('%s/%s\n'%(outdir_ims, f)) + list_file.close() + + print ("\nArgs:", args ) + print ("\nidx_count_tot_dic:", idx_count_tot_dic ) + print ("\nidx_count_dic:", idx_count_dic ) + print ("\nArgs:", args ) + print ("\ndf.columns:", list(df.columns) ) + print ("Number of objects:", len(df) ) + print ("Number of original images used:", win_iter ) + print ("Number of orginal+augmented images used:", len(os.listdir(outdir_ims)) ) + cats = np.unique(df['Category']) + print ("Categories in image file:", im_file, ':', cats ) + for c in cats: + print ("Number of items of category:", category, ":", len(df[df['Category'] == c]) ) + + # print (to file + lines = ['Args ' + str(args) + '\n', + 'Categories in image file: ' + im_file + ' : ' + str(cats) + '\n', + 'Number of objects: ' + str(len(df)) + '\n', + 'Number of original images used: ' + str(win_iter) + '\n', + 'Number of orginal+augmented images used: ' + str(len(os.listdir(outdir_ims))) + '\n', + ] + + log_file = os.path.join(outdir_tot, 'log.txt') + f = open(log_file,'w') + for l in lines: + f.write(l) + f.close() + + return + +############################################################################### +if __name__ == "__main__": + main() + diff --git a/yolt2/Makefile b/yolt2/Makefile index 4bc3f3b..7bf2c14 100755 --- a/yolt2/Makefile +++ b/yolt2/Makefile @@ -1,5 +1,5 @@ GPU=1 -CUDNN=1 +CUDNN=0 OPENCV=1 DEBUG=0 @@ -11,7 +11,7 @@ ARCH= -gencode arch=compute_50,code=[sm_50,compute_50] \ -gencode arch=compute_60,code=[sm_60,compute_60] \ -gencode arch=compute_61,code=[sm_61,compute_61] \ -gencode arch=compute_62,code=[sm_62,compute_62] \ - -gencode arch=compute_70,code=[sm_70,compute_70] + -gencode arch=compute_70,code=[sm_70,compute_70] \ # -gencode arch=compute_75,code=[sm_75,compute_75] # ARCH= -gencode arch=compute_30,code=sm_30 \ diff --git a/yolt2/src/yolt2.c b/yolt2/src/yolt2.c index 2754bf4..b28fddc 100644 --- a/yolt2/src/yolt2.c +++ b/yolt2/src/yolt2.c @@ -110,11 +110,11 @@ void save_image_ave2(image im, char *out_dir, const char *name) if(!success) fprintf(stderr, "Failed to write image %s\n", buff); } -void train_yolt2(char *cfgfile, char *weightfile, char *train_images, char *results_dir, int nbands, char *loss_file)//, int *gpus, int ngpus)//, int reset_seen) +void train_yolt2(char *cfgfile, char *weightfile, char *train_images, char *results_dir, int nbands, char *loss_file, int *gpus, int ngpus, int reset_seen) { - int reset_seen = 1; - int ngpus = 1; - int *gpus; + // int reset_seen = 1; + // int ngpus = 2; + // int *gpus; srand(time(0)); //data_seed = time(0); @@ -136,53 +136,78 @@ void train_yolt2(char *cfgfile, char *weightfile, char *train_images, char *resu fclose(lossfile); fprintf(stderr, "%s,%s,%s,%s\n", "Batch_Num", "BatchSize", "N_Train_Ims", "Loss"); - network net = parse_network_cfg(cfgfile); - network *nets = calloc(ngpus, sizeof(network)); - int i; - int imgs; +// network net = parse_network_cfg(cfgfile); +// network *nets = calloc(ngpus, sizeof(network)); +// int i; +// int imgs; +// +// if(ngpus == 1){ +// //////////////// +// // single gpu +// //network net = parse_network_cfg(cfgfile); +// if(weightfile){ +// load_weights(&net, weightfile); +// } +// +// //if using pretrained network, reset net.seen +// if(reset_seen){ +// *net.seen = 0; +// } +// +// imgs = net.batch*net.subdivisions; +// i = *net.seen/imgs; +// +// //////////////////// +// } else { +// ///////////////////// +// // multi gpu +// network *nets = calloc(ngpus, sizeof(network)); +// +// srand(time(0)); +// int seed = rand(); +// int i; +// for(i = 0; i < ngpus; ++i){ +// srand(seed); +// #ifdef GPU +// cuda_set_device(gpus[i]); +// #endif +// nets[i] = parse_network_cfg(cfgfile); +// if(weightfile){ +// load_weights(&nets[i], weightfile); +// } +// if(reset_seen) *nets[i].seen = 0; +// nets[i].learning_rate *= ngpus; +// } +// srand(time(0)); +// network net = nets[0]; +// +// imgs = net.batch * net.subdivisions * ngpus; +// } +// //////////////////// - if(ngpus == 1){ - //////////////// - // single gpu - //network net = parse_network_cfg(cfgfile); - if(weightfile){ - load_weights(&net, weightfile); - } - - //if using pretrained network, reset net.seen - if(reset_seen){ - *net.seen = 0; - } - - imgs = net.batch*net.subdivisions; - i = *net.seen/imgs; - //////////////////// - } else { - ///////////////////// - // multi gpu - network *nets = calloc(ngpus, sizeof(network)); + network *nets = calloc(ngpus, sizeof(network)); - srand(time(0)); - int seed = rand(); - int i; - for(i = 0; i < ngpus; ++i){ - srand(seed); + srand(time(0)); + int seed = rand(); + int i; + for(i = 0; i < ngpus; ++i){ + srand(seed); #ifdef GPU - cuda_set_device(gpus[i]); + cuda_set_device(gpus[i]); #endif - nets[i] = parse_network_cfg(cfgfile); - if(weightfile){ - load_weights(&nets[i], weightfile); - } - if(reset_seen) *nets[i].seen = 0; - nets[i].learning_rate *= ngpus; - } - srand(time(0)); - network net = nets[0]; - - imgs = net.batch * net.subdivisions * ngpus; - //////////////////// + nets[i] = parse_network_cfg(cfgfile); + if(weightfile){ + load_weights(&nets[i], weightfile); + } + if(reset_seen) *nets[i].seen = 0; + nets[i].learning_rate *= ngpus; } + srand(time(0)); + network net = nets[0]; + + int imgs = net.batch * net.subdivisions * ngpus; + i = *net.seen/imgs; + fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); fprintf(stderr, "\n\n\n\n\n\nNum images = %d,\ni= %d\n", imgs, i); @@ -365,7 +390,7 @@ void validate_yolt2(char *cfgfile, char *weightfile, char *valid_list_loc, } set_batch_network(&net, 1); fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); - fprintf(stderr, "valid_list_loc: %s\n", valid_list_loc); + fprintf(stderr, "test_list_loc: %s\n", valid_list_loc); srand(time(0)); @@ -374,6 +399,8 @@ void validate_yolt2(char *cfgfile, char *weightfile, char *valid_list_loc, layer l = net.layers[net.n-1]; int classes = l.classes; + fprintf(stderr, "n classes %d\n", classes); + //int square = l.sqrt; //int side = l.side; @@ -433,7 +460,9 @@ void validate_yolt2(char *cfgfile, char *weightfile, char *valid_list_loc, //clock_t ticks; for(i = nthreads; i < m+nthreads; i += nthreads){ - fprintf(stderr, "%d / %d \n", i, m); + if (i % 50 == 0){ + fprintf(stderr, "%d / %d \n", i, m); + } for(t = 0; t < nthreads && i+t-nthreads < m; ++t){ pthread_join(thr[t], 0); val[t] = buf[t]; @@ -453,8 +482,10 @@ void validate_yolt2(char *cfgfile, char *weightfile, char *valid_list_loc, char *id = path; //fprintf(stderr, "path: %s\n", path); - fprintf(stderr, "validate id: %s\n", id); - //fprintf(stderr, "test0\n"); + if (i % 50 == 0){ + fprintf(stderr, "test id: %s\n", id); + //fprintf(stderr, "test0\n"); + } float *X = val_resized[t].data; float *predictions = network_predict(net, X); @@ -492,14 +523,16 @@ void validate_yolt2(char *cfgfile, char *weightfile, char *valid_list_loc, } } + + //fprintf(stderr, "test_check_0\n"); for(j = 0; j < classes; ++j){ + // fprintf(stderr, "close class: %d\n", j); if(fps) fclose(fps[j]); } - + //fprintf(stderr, "test_check_1\n"); //time(&stop); clock_gettime(CLOCK_MONOTONIC, &tend); - - + fprintf(stderr, "Total Detection Time: %.5f Seconds\n", ((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) - ((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec)); //fprintf(stderr, "Total Detection Time: %.4f Seconds\n", (double)(time(0) - start)); @@ -621,13 +654,17 @@ void run_yolt2(int argc, char **argv) int nbands = (argc > 13) ? atoi(argv[13]): 0; char *loss_file = (argc > 14) ? argv[14]: 0; float min_retain_prob = (argc > 15) ? atof(argv[15]): 0.0; + int ngpus = (argc > 16) ? atoi(argv[16]): 0; + int reset_seen = 1; // switch to reset the number of observations already seen + // turn names_str into names_list - fprintf(stderr, "\nRun YOLT.C...\n"); + fprintf(stderr, "\nRun YOLT2.C...\n"); fprintf(stderr, "Plot Probablility Threshold: %f\n", plot_thresh); fprintf(stderr, "Label_str: %s\n", names_str); fprintf(stderr, "len(names): %i\n", len_names); fprintf(stderr, "num channels: %i\n", nbands); + fprintf(stderr, "ngpus: %i\n", ngpus); char **names; if(len_names > 0){ @@ -644,6 +681,30 @@ void run_yolt2(int argc, char **argv) //fprintf(stderr, "Load Network:\n"); } + //char *gpu_list = find_char_arg(argc, argv, "-gpus", 0); + //int ngpus = 0; + int *gpus = 0; + int gpu = 0; + if(ngpus > 1){ + // printf("%s\n", gpu_list); + //int len = strlen(gpu_list); + //ngpus = 1; + int i; + //for(i = 0; i < len; ++i){ + // if (gpu_list[i] == ',') ++ngpus; + //} + gpus = calloc(ngpus, sizeof(int)); + for(i = 0; i < ngpus; ++i){ + gpus[i] = i; + //gpus[i] = atoi(gpu_list); + //gpu_list = strchr(gpu_list, ',')+1; + } + } else { + gpu = gpu_index; + gpus = &gpu; + ngpus = 1; + } + if(0==strcmp(argv[2], "test")){ //load labels images image voc_labels[len_names]; @@ -658,7 +719,7 @@ void run_yolt2(int argc, char **argv) test_yolt2(cfg, weights, test_filename, plot_thresh, nms_thresh, names, voc_labels, len_names, nbands, results_dir); } - else if(0==strcmp(argv[2], "train")) train_yolt2(cfg, weights, train_images, results_dir, nbands, loss_file); + else if(0==strcmp(argv[2], "train")) train_yolt2(cfg, weights, train_images, results_dir, nbands, loss_file, gpus, ngpus, reset_seen); else if(0==strcmp(argv[2], "valid")) validate_yolt2(cfg, weights, valid_list_loc, nms_thresh, names, results_dir, nbands, min_retain_prob); diff --git a/yolt3/Makefile b/yolt3/Makefile index dd45892..a7c89b9 100755 --- a/yolt3/Makefile +++ b/yolt3/Makefile @@ -1,5 +1,5 @@ GPU=1 -CUDNN=1 +CUDNN=0 OPENCV=1 OPENMP=0 DEBUG=0 @@ -21,7 +21,7 @@ ARCH= -gencode arch=compute_50,code=[sm_50,compute_50] \ -gencode arch=compute_61,code=[sm_61,compute_61] \ -gencode arch=compute_62,code=[sm_62,compute_62] \ -gencode arch=compute_70,code=[sm_70,compute_70] - #-gencode arch=compute_75,code=[sm_75,compute_75] +# -gencode arch=compute_75,code=[sm_75,compute_75] # ARCH= -gencode arch=compute_30,code=sm_30 \ # -gencode arch=compute_35,code=sm_35 \ diff --git a/yolt3/cfg/yolov3 copy.cfg b/yolt3/cfg/yolov3_512.cfg similarity index 99% rename from yolt3/cfg/yolov3 copy.cfg rename to yolt3/cfg/yolov3_512.cfg index 1a9b27d..6273e28 100755 --- a/yolt3/cfg/yolov3 copy.cfg +++ b/yolt3/cfg/yolov3_512.cfg @@ -5,8 +5,8 @@ # Training batch=64 subdivisions=16 -width=544 -height=544 +width=512 +height=512 channels=3 momentum=0.9 decay=0.0005 diff --git a/yolt3/examples/yolt3.c b/yolt3/examples/yolt3.c index 1b6b004..bd56e77 100644 --- a/yolt3/examples/yolt3.c +++ b/yolt3/examples/yolt3.c @@ -169,11 +169,8 @@ void print_yolt_detections(FILE **fps, char *id, detection *dets, int total, int } // AVE -void train_yolt3(char *cfgfile, char *weightfile, char *train_images, char *results_dir, int nbands, char *loss_file)//, int *gpus, int ngpus, int clear) +void train_yolt3(char *cfgfile, char *weightfile, char *train_images, char *results_dir, int nbands, char *loss_file, int *gpus, int ngpus, int reset_seen) { - int reset_seen = 1; - int ngpus = 1; - int *gpus; srand(time(0)); char *base = basecfg(cfgfile); @@ -202,28 +199,20 @@ void train_yolt3(char *cfgfile, char *weightfile, char *train_images, char *resu srand(time(0)); int seed = rand(); int i; - fprintf(stderr, "%s\n", "Check0"); - // cuda_set_device(gpus[0]); - fprintf(stderr, "%s\n", "Check1"); - nets[0] = load_network(cfgfile, weightfile, reset_seen); - fprintf(stderr, "%s\n", "Check2"); + for(i = 0; i < ngpus; ++i){ + srand(seed); +#ifdef GPU + cuda_set_device(gpus[i]); +#endif + nets[i] = load_network(cfgfile, weightfile, reset_seen); + // if(reset_seen) *nets[i].seen = 0; + nets[i]->learning_rate *= ngpus; + } + srand(time(0)); network *net = nets[0]; - fprintf(stderr, "%s\n", "Check3"); - - - // multi gpu -// for(i = 0; i < ngpus; ++i){ -// srand(seed); -// #ifdef GPU -// cuda_set_device(gpus[i]); -// #endif -// nets[i] = load_network(cfgfile, weightfile, clear); -// nets[i]->learning_rate *= ngpus; -// } -// srand(time(0)); -// network *net = nets[0]; int imgs = net->batch * net->subdivisions * ngpus; + i = 0; // *net.seen/imgs; printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay); fprintf(stderr, "\n\n\n\nNum images = %d,\ni= %d\n", imgs, i); data train, buffer; @@ -359,7 +348,7 @@ void validate_yolt3(char *cfgfile, char *weightfile, char *valid_list_loc, set_batch_network(net, 1); fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay); //fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); - fprintf(stderr, "valid_list_loc: %s\n", valid_list_loc); + fprintf(stderr, "test_list_loc: %s\n", valid_list_loc); srand(time(0)); list *plist = get_paths(valid_list_loc); @@ -438,7 +427,7 @@ void validate_yolt3(char *cfgfile, char *weightfile, char *valid_list_loc, char *id = path; //fprintf(stderr, "path: %s\n", path); if (count%10 == 0){ - fprintf(stderr, "%d, validate id: %s\n", i, id); + fprintf(stderr, "%d, test id: %s\n", i, id); } float *X = val_resized[t].data; @@ -570,36 +559,65 @@ void run_yolt3(int argc, char **argv) int len_names = (argc > 12) ? atoi(argv[12]): 0; int nbands = (argc > 13) ? atoi(argv[13]): 0; char *loss_file = (argc > 14) ? argv[14]: 0; + float min_retain_prob = (argc > 15) ? atof(argv[15]): 0.0; + int ngpus = (argc > 16) ? atoi(argv[16]): 0; + + int reset_seen = 1; // switch to reset the number of observations already seen + + // turn names_str into names_list + fprintf(stderr, "\nRun YOLT3.C...\n"); + fprintf(stderr, "Plot Probablility Threshold: %f\n", plot_thresh); + fprintf(stderr, "Label_str: %s\n", names_str); + fprintf(stderr, "len(names): %i\n", len_names); + fprintf(stderr, "num channels: %i\n", nbands); + fprintf(stderr, "ngpus: %i\n", ngpus); - // get gpu list - char *gpu_list = find_char_arg(argc, argv, "-gpus", 0); + // // get gpu list + //char *gpu_list = find_char_arg(argc, argv, "-gpus", 0); + //int ngpus = 0; int *gpus = 0; int gpu = 0; - int ngpus = 0; - if(gpu_list){ - printf("%s\n", gpu_list); - int len = strlen(gpu_list); - ngpus = 1; + if(ngpus > 1){ + // printf("%s\n", gpu_list); + //int len = strlen(gpu_list); + //ngpus = 1; int i; - for(i = 0; i < len; ++i){ - if (gpu_list[i] == ',') ++ngpus; - } + //for(i = 0; i < len; ++i){ + // if (gpu_list[i] == ',') ++ngpus; + //} gpus = calloc(ngpus, sizeof(int)); for(i = 0; i < ngpus; ++i){ - gpus[i] = atoi(gpu_list); - gpu_list = strchr(gpu_list, ',')+1; + gpus[i] = i; + //gpus[i] = atoi(gpu_list); + //gpu_list = strchr(gpu_list, ',')+1; } } else { gpu = gpu_index; gpus = &gpu; ngpus = 1; } - - fprintf(stderr, "\nRun YOLT.C...\n"); - fprintf(stderr, "Plot Probablility Threshold: %f\n", plot_thresh); - fprintf(stderr, "Label_str: %s\n", names_str); - fprintf(stderr, "len(names): %i\n", len_names); - fprintf(stderr, "num channels: %i\n", nbands); + // char *gpu_list = find_char_arg(argc, argv, "-gpus", 0); + // int *gpus = 0; + // int gpu = 0; + // int ngpus = 0; + // if(gpu_list){ + // printf("%s\n", gpu_list); + // int len = strlen(gpu_list); + // ngpus = 1; + // int i; + // for(i = 0; i < len; ++i){ + // if (gpu_list[i] == ',') ++ngpus; + // } + // gpus = calloc(ngpus, sizeof(int)); + // for(i = 0; i < ngpus; ++i){ + // gpus[i] = atoi(gpu_list); + // gpu_list = strchr(gpu_list, ',')+1; + // } + // } else { + // gpu = gpu_index; + // gpus = &gpu; + // ngpus = 1; + // } // turn names_str into names_list char **names; @@ -618,7 +636,7 @@ void run_yolt3(int argc, char **argv) } // train - if(0==strcmp(argv[2], "train")) train_yolt3(cfg, weights, train_images, results_dir, nbands, loss_file);//, + if(0==strcmp(argv[2], "train")) train_yolt3(cfg, weights, train_images, results_dir, nbands, loss_file, gpus, ngpus, reset_seen); //0, 1, 1); //gpus, ngpus, clear);