| @@ -0,0 +1,158 @@ | |||
| import cv2 | |||
| import os | |||
| import numpy as np | |||
| import sys | |||
| def draw_poly(img, bounding_poly): | |||
| pts = np.array(bounding_poly, np.int32) | |||
| #http://stackoverflow.com/a/15343106/3479446 | |||
| mask = np.zeros(img.shape[:2], dtype=np.uint8) | |||
| roi_corners = np.array([pts], dtype=np.int32) | |||
| ignore_mask_color = (255,) | |||
| cv2.fillPoly(mask, roi_corners, ignore_mask_color, lineType=cv2.LINE_8) | |||
| return mask | |||
| def post_process(img): | |||
| # img = open_close(img) | |||
| img = get_largest_cc(img) | |||
| img = fill_holes(img) | |||
| # img = min_area_rectangle(img) | |||
| img, coords = improve_min_area_rectangle(img) | |||
| return img, coords | |||
| def open_close(img): | |||
| kernel = np.ones((3,3),np.uint8) | |||
| erosion = cv2.erode(img,kernel,iterations = 15) | |||
| dilation = cv2.dilate(erosion,kernel,iterations = 15) | |||
| return dilation | |||
| def get_largest_cc(img): | |||
| img = img.copy() | |||
| ret, th = cv2.threshold(img,127,255,cv2.THRESH_BINARY) | |||
| connectivity = 4 | |||
| output= cv2.connectedComponentsWithStats(th, connectivity, cv2.CV_32S) | |||
| cnts = output[2][1:,4] | |||
| largest = cnts.argmax() + 1 | |||
| img[output[1] != largest] = 0 | |||
| return img | |||
| def get_iou(gt_img, pred_img): | |||
| inter = gt_img & pred_img | |||
| union = gt_img | pred_img | |||
| iou = np.count_nonzero(inter) / float(np.count_nonzero(union)) | |||
| return iou | |||
| def draw_box(img, box): | |||
| box = np.int0(box) | |||
| draw = np.zeros_like(img) | |||
| cv2.drawContours(draw,[box],0,(255),-1) | |||
| return draw | |||
| def compute_iou(img, box): | |||
| # box = np.int0(box) | |||
| # draw = np.zeros_like(img) | |||
| # cv2.drawContours(draw,[box],0,(255),-1) | |||
| draw = draw_box(img, box) | |||
| v = get_iou(img, draw) | |||
| return v | |||
| def step_box(img, box, step_size=1): | |||
| best_val = -1 | |||
| best_box = None | |||
| for index, x in np.ndenumerate(box): | |||
| for d in [-step_size, step_size]: | |||
| alt_box = box.copy() | |||
| alt_box[index] = x + d | |||
| v = compute_iou(img, alt_box) | |||
| if best_val < v: | |||
| best_val = v | |||
| best_box = alt_box | |||
| return best_val, best_box | |||
| def improve_min_area_rectangle(img): | |||
| img = img.copy() | |||
| _, contours,_ = cv2.findContours(img, 1, 2) | |||
| cnt = contours[0] | |||
| rect = cv2.minAreaRect(cnt) | |||
| box = cv2.boxPoints(rect) | |||
| best_val = compute_iou(img, box) | |||
| best_box = box | |||
| while True: | |||
| new_val, new_box = step_box(img, best_box, step_size=1) | |||
| # print new_val | |||
| if new_val <= best_val: | |||
| break | |||
| best_val = new_val | |||
| best_box = new_box | |||
| return draw_box(img, best_box), best_box | |||
| def min_area_rectangle(img): | |||
| img = img.copy() | |||
| _, contours,_ = cv2.findContours(img, 1, 2) | |||
| cnt = contours[0] | |||
| rect = cv2.minAreaRect(cnt) | |||
| box = cv2.boxPoints(rect) | |||
| box = np.int0(box) | |||
| draw = np.zeros_like(img) | |||
| cv2.drawContours(draw,[box],0,(255),-1) | |||
| return draw | |||
| def fill_holes(img): | |||
| im_th = img.copy() | |||
| # Copy the thresholded image. | |||
| im_floodfill = im_th.copy() | |||
| # Mask used to flood filling. | |||
| # Notice the size needs to be 2 pixels than the image. | |||
| h, w = im_th.shape[:2] | |||
| mask = np.zeros((h+2, w+2), np.uint8) | |||
| # Floodfill from point (0, 0) | |||
| if img[0,0] != 0: | |||
| print "WARNING: Filling something you shouldn't" | |||
| cv2.floodFill(im_floodfill, mask, (0,0), 255); | |||
| # Invert floodfilled image | |||
| im_floodfill_inv = cv2.bitwise_not(im_floodfill) | |||
| # Combine the two images to get the foreground. | |||
| im_out = im_th | im_floodfill_inv | |||
| return im_out | |||
| if __name__ == "__main__": | |||
| pred_folder = sys.argv[1] | |||
| out_folder = sys.argv[2] | |||
| pred_imgs = {} | |||
| for root, folders, files in os.walk(pred_folder): | |||
| for f in files: | |||
| if f.endswith(".png"): | |||
| pred_imgs[f] = os.path.join(root, f) | |||
| for k in pred_imgs: | |||
| pred_img = cv2.imread(pred_imgs[k], 0) | |||
| post_img = post_process(pred_img) | |||
| cv2.imwrite(os.path.join(out_folder, k), post_img) | |||
| @@ -1,114 +0,0 @@ | |||
| #!/usr/bin/python | |||
| import os | |||
| import sys | |||
| import collections | |||
| import argparse | |||
| import numpy as np | |||
| import matplotlib | |||
| matplotlib.use("AGG") | |||
| import matplotlib.pyplot as plt | |||
| import caffe | |||
| import cv2 | |||
| import random | |||
| import scipy.ndimage as nd | |||
| def safe_mkdir(_dir): | |||
| try: | |||
| os.makedirs(_dir) | |||
| except: | |||
| pass | |||
| def predict(network, im, output_blob, args): | |||
| network.blobs["data"].data[0,:,:,:] = im | |||
| network.forward() | |||
| #response = network.blobs[output_blob].data[0,:].copy() | |||
| #return np.argmax(response, axis=0) | |||
| response = network.blobs[output_blob].data[0,0,:,:].copy() | |||
| response[response >= 0.5] = 1 | |||
| response[response <= 0.5] = 0 | |||
| return response | |||
| def presolve(net, args): | |||
| net.blobs["data"].reshape(args.batch_size, 3 if args.color else 1, args.image_size, args.image_size) | |||
| net.blobs["gt"].reshape(args.batch_size, 1, args.image_size, args.image_size) | |||
| def main(args): | |||
| net = caffe.Net(args.net_file, args.weight_file, caffe.TEST) | |||
| presolve(net, args) | |||
| file_list = map(lambda s: s.strip(), open(args.test_manifest, 'r').readlines()) | |||
| for idx, line in enumerate(file_list): | |||
| if idx % args.print_count == 0: | |||
| print "Processed %d/%d Images" % (idx, len(file_list)) | |||
| tokens = line.split(',') | |||
| f = tokens[0] | |||
| resolved = os.path.join(args.dataset_dir, f) | |||
| im = cv2.imread(resolved, 1 if args.color else 0) | |||
| _input = args.scale * (cv2.resize(im, (args.image_size, args.image_size)) - args.mean) | |||
| if _input.ndim > 2: | |||
| _input = np.transpose(_input, (2, 0, 1)) | |||
| output = predict(net, _input, 'out', args) | |||
| out_fn = os.path.join(args.out_dir, f.replace('/','_')[:-4] + ".png") | |||
| cv2.imwrite(out_fn, (255 * output).astype(np.uint8)) | |||
| def get_args(): | |||
| parser = argparse.ArgumentParser(description="Outputs binary predictions") | |||
| parser.add_argument("net_file", | |||
| help="The deploy.prototxt") | |||
| parser.add_argument("weight_file", | |||
| help="The .caffemodel") | |||
| parser.add_argument("dataset_dir", | |||
| help="The dataset to be evaluated") | |||
| parser.add_argument("test_manifest", | |||
| help="txt file listing images to train on") | |||
| parser.add_argument("--out-dir", default='out', type=str, | |||
| help="Dump images") | |||
| parser.add_argument("--gpu", type=int, default=0, | |||
| help="GPU to use for running the network") | |||
| parser.add_argument("-c", "--color", default=False, action='store_true', | |||
| help="Training batch size") | |||
| parser.add_argument("-m", "--mean", type=float, default=127., | |||
| help="Mean value for data preprocessing") | |||
| parser.add_argument("-s", "--scale", type=float, default=0.0039, | |||
| help="Optional pixel scale factor") | |||
| parser.add_argument("-b", "--batch-size", default=2, type=int, | |||
| help="Training batch size") | |||
| parser.add_argument("--image-size", default=256, type=int, | |||
| help="Size of images for input to prediction") | |||
| parser.add_argument("--print-count", default=10, type=int, | |||
| help="Print interval") | |||
| args = parser.parse_args() | |||
| print args | |||
| return args | |||
| if __name__ == "__main__": | |||
| args = get_args() | |||
| safe_mkdir(args.out_dir) | |||
| if args.gpu >= 0: | |||
| caffe.set_device(args.gpu) | |||
| caffe.set_mode_gpu() | |||
| else: | |||
| caffe.set_mode_cpu() | |||
| main(args) | |||
| @@ -0,0 +1,112 @@ | |||
| #!/usr/bin/python | |||
| import os | |||
| import sys | |||
| import argparse | |||
| import numpy as np | |||
| import caffe | |||
| import cv2 | |||
| from process_pixel_labels import post_process | |||
| NET_FILE = './models/cbad_train_val.prototxt' | |||
| WEIGHT_FILE = './models/cbad_weights.prototxt' | |||
| def safe_mkdir(_dir): | |||
| try: | |||
| os.makedirs(_dir) | |||
| except: | |||
| pass | |||
| def predict(network, im, output_blob, args): | |||
| network.blobs["data"].data[0,:,:,:] = im | |||
| network.forward() | |||
| if args.model == 'ohio': | |||
| # sigmoid | |||
| response = network.blobs[output_blob].data[0,0,:,:].copy() | |||
| response[response >= 0.5] = 1 | |||
| response[response <= 0.5] = 0 | |||
| return response | |||
| else: | |||
| # softmax | |||
| response = network.blobs[output_blob].data[0,:].copy() | |||
| return np.argmax(response, axis=0) | |||
| def presolve(net, args): | |||
| net.blobs["data"].reshape(args.batch_size, 3, args.image_size, args.image_size) | |||
| net.blobs["gt"].reshape(args.batch_size, 1, args.image_size, args.image_size) | |||
| def main(args): | |||
| net = caffe.Net(NET_FILE, WEIGHT_FILE, caffe.TEST) | |||
| presolve(net, args) | |||
| file_list = map(lambda s: s.strip(), open(args.manifest, 'r').readlines()) | |||
| fd = open(args.out_file, 'w') | |||
| for idx, line in enumerate(file_list): | |||
| if idx % args.print_count == 0: | |||
| print "Processed %d/%d Images" % (idx, len(file_list)) | |||
| tokens = line.split(',') | |||
| f = tokens[0] | |||
| resolved = os.path.join(args.image_dir, f) | |||
| im = cv2.imread(resolved, 1) | |||
| _input = 0.0039 * (cv2.resize(im, (256, 256)) - 127.) | |||
| _input = np.transpose(_input, (2, 0, 1)) | |||
| raw = (255 * predict(net, _input, 'out', args)).astype(np.uint8) | |||
| out_fn = os.path.join(args.out_dir, f.replace('/','_')[:-4] + "_raw.png") | |||
| cv2.imwrite(out_fn, raw) | |||
| post, coords = post_process(raw) | |||
| out_fn = os.path.join(args.out_dir, f.replace('/','_')[:-4] + "_post.png") | |||
| cv2.imwrite(out_fn, post) | |||
| def get_args(): | |||
| parser = argparse.ArgumentParser(description="Outputs binary predictions") | |||
| parser.add_argument("image_dir", | |||
| help="The directory where images are stored") | |||
| parser.add_argument("manifest", | |||
| help="txt file listing images relative to image_dir") | |||
| parser.add_argument("model", | |||
| help="[cbad|ohio]") | |||
| parser.add_argument("out_file", type=str, | |||
| help="Output file") | |||
| parser.add_argument("--out-dir", type=str, default=out, | |||
| help="") | |||
| parser.add_argument("--gpu", type=int, default=0, | |||
| help="GPU to use for running the network") | |||
| parser.add_argument("--print-count", default=10, type=int, | |||
| help="Print interval") | |||
| args = parser.parse_args() | |||
| print args | |||
| return args | |||
| if __name__ == "__main__": | |||
| args = get_args() | |||
| safe_mkdir(args.out_dir) | |||
| if args.model == 'ohio': | |||
| NET_FILE = './models/ohio_train_val.prototxt' | |||
| WEIGHT_FILE = './models/ohio_weights.caffemodel' | |||
| if args.gpu >= 0: | |||
| caffe.set_device(args.gpu) | |||
| caffe.set_mode_gpu() | |||
| else: | |||
| caffe.set_mode_cpu() | |||
| main(args) | |||