|
@@ -0,0 +1,473 @@
|
|
|
|
+import matplotlib.pyplot as plt
|
|
|
|
+import numpy as np
|
|
|
|
+import cv2
|
|
|
|
+import pandas as pd
|
|
|
|
+from shapely.wkt import loads as wkt_loads
|
|
|
|
+import tifffile as tiff
|
|
|
|
+import os
|
|
|
|
+import random
|
|
|
|
+from keras.models import Model
|
|
|
|
+from keras.layers import Input, merge, Convolution2D, MaxPooling2D, UpSampling2D, Reshape, core, Dropout
|
|
|
|
+from keras.optimizers import Adam
|
|
|
|
+from keras.callbacks import ModelCheckpoint, LearningRateScheduler
|
|
|
|
+from keras import backend as K
|
|
|
|
+from sklearn.metrics import jaccard_similarity_score
|
|
|
|
+from shapely.geometry import MultiPolygon, Polygon
|
|
|
|
+import shapely.wkt
|
|
|
|
+import shapely.affinity
|
|
|
|
+from collections import defaultdict
|
|
|
|
+
|
|
|
|
+N_Cls = 10
|
|
|
|
+inDir = '/home/n01z3/dataset/dstl'
|
|
|
|
+DF = pd.read_csv(inDir + '/train_wkt_v4.csv')
|
|
|
|
+GS = pd.read_csv(inDir + '/grid_sizes.csv', names=['ImageId', 'Xmax', 'Ymin'], skiprows=1)
|
|
|
|
+SB = pd.read_csv(os.path.join(inDir, 'sample_submission.csv'))
|
|
|
|
+ISZ = 160
|
|
|
|
+smooth = 1e-12
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def _convert_coordinates_to_raster(coords, img_size, xymax):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ Xmax, Ymax = xymax
|
|
|
|
+ H, W = img_size
|
|
|
|
+ W1 = 1.0 * W * W / (W + 1)
|
|
|
|
+ H1 = 1.0 * H * H / (H + 1)
|
|
|
|
+ xf = W1 / Xmax
|
|
|
|
+ yf = H1 / Ymax
|
|
|
|
+ coords[:, 1] *= yf
|
|
|
|
+ coords[:, 0] *= xf
|
|
|
|
+ coords_int = np.round(coords).astype(np.int32)
|
|
|
|
+ return coords_int
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def _get_xmax_ymin(grid_sizes_panda, imageId):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ xmax, ymin = grid_sizes_panda[grid_sizes_panda.ImageId == imageId].iloc[0, 1:].astype(float)
|
|
|
|
+ return (xmax, ymin)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def _get_polygon_list(wkt_list_pandas, imageId, cType):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ df_image = wkt_list_pandas[wkt_list_pandas.ImageId == imageId]
|
|
|
|
+ multipoly_def = df_image[df_image.ClassType == cType].MultipolygonWKT
|
|
|
|
+ polygonList = None
|
|
|
|
+ if len(multipoly_def) > 0:
|
|
|
|
+ assert len(multipoly_def) == 1
|
|
|
|
+ polygonList = wkt_loads(multipoly_def.values[0])
|
|
|
|
+ return polygonList
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def _get_and_convert_contours(polygonList, raster_img_size, xymax):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ perim_list = []
|
|
|
|
+ interior_list = []
|
|
|
|
+ if polygonList is None:
|
|
|
|
+ return None
|
|
|
|
+ for k in range(len(polygonList)):
|
|
|
|
+ poly = polygonList[k]
|
|
|
|
+ perim = np.array(list(poly.exterior.coords))
|
|
|
|
+ perim_c = _convert_coordinates_to_raster(perim, raster_img_size, xymax)
|
|
|
|
+ perim_list.append(perim_c)
|
|
|
|
+ for pi in poly.interiors:
|
|
|
|
+ interior = np.array(list(pi.coords))
|
|
|
|
+ interior_c = _convert_coordinates_to_raster(interior, raster_img_size, xymax)
|
|
|
|
+ interior_list.append(interior_c)
|
|
|
|
+ return perim_list, interior_list
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def _plot_mask_from_contours(raster_img_size, contours, class_value=1):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ img_mask = np.zeros(raster_img_size, np.uint8)
|
|
|
|
+ if contours is None:
|
|
|
|
+ return img_mask
|
|
|
|
+ perim_list, interior_list = contours
|
|
|
|
+ cv2.fillPoly(img_mask, perim_list, class_value)
|
|
|
|
+ cv2.fillPoly(img_mask, interior_list, 0)
|
|
|
|
+ return img_mask
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def generate_mask_for_image_and_class(raster_size, imageId, class_type, grid_sizes_panda=GS, wkt_list_pandas=DF):
|
|
|
|
+ # __author__ = visoft
|
|
|
|
+ # https://www.kaggle.com/visoft/dstl-satellite-imagery-feature-detection/export-pixel-wise-mask
|
|
|
|
+ xymax = _get_xmax_ymin(grid_sizes_panda, imageId)
|
|
|
|
+ polygon_list = _get_polygon_list(wkt_list_pandas, imageId, class_type)
|
|
|
|
+ contours = _get_and_convert_contours(polygon_list, raster_size, xymax)
|
|
|
|
+ mask = _plot_mask_from_contours(raster_size, contours, 1)
|
|
|
|
+ return mask
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def M(image_id):
|
|
|
|
+ # __author__ = amaia
|
|
|
|
+ # https://www.kaggle.com/aamaia/dstl-satellite-imagery-feature-detection/rgb-using-m-bands-example
|
|
|
|
+ filename = os.path.join(inDir, 'sixteen_band', '{}_M.tif'.format(image_id))
|
|
|
|
+ img = tiff.imread(filename)
|
|
|
|
+ img = np.rollaxis(img, 0, 3)
|
|
|
|
+ return img
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def stretch_n(bands, lower_percent=5, higher_percent=95):
|
|
|
|
+ out = np.zeros_like(bands)
|
|
|
|
+ n = bands.shape[2]
|
|
|
|
+ for i in range(n):
|
|
|
|
+ a = 0 # np.min(band)
|
|
|
|
+ b = 1 # np.max(band)
|
|
|
|
+ c = np.percentile(bands[:, :, i], lower_percent)
|
|
|
|
+ d = np.percentile(bands[:, :, i], higher_percent)
|
|
|
|
+ t = a + (bands[:, :, i] - c) * (b - a) / (d - c)
|
|
|
|
+ t[t < a] = a
|
|
|
|
+ t[t > b] = b
|
|
|
|
+ out[:, :, i] = t
|
|
|
|
+
|
|
|
|
+ return out.astype(np.float32)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def jaccard_coef(y_true, y_pred):
|
|
|
|
+ # __author__ = Vladimir Iglovikov
|
|
|
|
+ intersection = K.sum(y_true * y_pred, axis=[0, -1, -2])
|
|
|
|
+ sum_ = K.sum(y_true + y_pred, axis=[0, -1, -2])
|
|
|
|
+
|
|
|
|
+ jac = (intersection + smooth) / (sum_ - intersection + smooth)
|
|
|
|
+
|
|
|
|
+ return K.mean(jac)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def jaccard_coef_int(y_true, y_pred):
|
|
|
|
+ # __author__ = Vladimir Iglovikov
|
|
|
|
+ y_pred_pos = K.round(K.clip(y_pred, 0, 1))
|
|
|
|
+
|
|
|
|
+ intersection = K.sum(y_true * y_pred_pos, axis=[0, -1, -2])
|
|
|
|
+ sum_ = K.sum(y_true + y_pred, axis=[0, -1, -2])
|
|
|
|
+ jac = (intersection + smooth) / (sum_ - intersection + smooth)
|
|
|
|
+ return K.mean(jac)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def stick_all_train():
|
|
|
|
+ print "let's stick all imgs together"
|
|
|
|
+ s = 835
|
|
|
|
+
|
|
|
|
+ x = np.zeros((5 * s, 5 * s, 8))
|
|
|
|
+ y = np.zeros((5 * s, 5 * s, N_Cls))
|
|
|
|
+
|
|
|
|
+ ids = sorted(DF.ImageId.unique())
|
|
|
|
+ print len(ids)
|
|
|
|
+ for i in range(5):
|
|
|
|
+ for j in range(5):
|
|
|
|
+ id = ids[5 * i + j]
|
|
|
|
+
|
|
|
|
+ img = M(id)
|
|
|
|
+ img = stretch_n(img)
|
|
|
|
+ print img.shape, id, np.amax(img), np.amin(img)
|
|
|
|
+ x[s * i:s * i + s, s * j:s * j + s, :] = img[:s, :s, :]
|
|
|
|
+ for z in range(N_Cls):
|
|
|
|
+ y[s * i:s * i + s, s * j:s * j + s, z] = generate_mask_for_image_and_class(
|
|
|
|
+ (img.shape[0], img.shape[1]), id, z + 1)[:s, :s]
|
|
|
|
+
|
|
|
|
+ print np.amax(y), np.amin(y)
|
|
|
|
+
|
|
|
|
+ np.save('data/x_trn_%d' % N_Cls, x)
|
|
|
|
+ np.save('data/y_trn_%d' % N_Cls, y)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def get_patches(img, msk, amt=10000, aug=True):
|
|
|
|
+ is2 = int(1.0 * ISZ)
|
|
|
|
+ xm, ym = img.shape[0] - is2, img.shape[1] - is2
|
|
|
|
+
|
|
|
|
+ x, y = [], []
|
|
|
|
+
|
|
|
|
+ tr = [0.4, 0.1, 0.1, 0.15, 0.3, 0.95, 0.1, 0.05, 0.001, 0.005]
|
|
|
|
+ for i in range(amt):
|
|
|
|
+ xc = random.randint(0, xm)
|
|
|
|
+ yc = random.randint(0, ym)
|
|
|
|
+
|
|
|
|
+ im = img[xc:xc + is2, yc:yc + is2]
|
|
|
|
+ ms = msk[xc:xc + is2, yc:yc + is2]
|
|
|
|
+
|
|
|
|
+ for j in range(N_Cls):
|
|
|
|
+ sm = np.sum(ms[:, :, j])
|
|
|
|
+ if 1.0 * sm / is2 ** 2 > tr[j]:
|
|
|
|
+ if aug:
|
|
|
|
+ if random.uniform(0, 1) > 0.5:
|
|
|
|
+ im = im[::-1]
|
|
|
|
+ ms = ms[::-1]
|
|
|
|
+ if random.uniform(0, 1) > 0.5:
|
|
|
|
+ im = im[:, ::-1]
|
|
|
|
+ ms = ms[:, ::-1]
|
|
|
|
+
|
|
|
|
+ x.append(im)
|
|
|
|
+ y.append(ms)
|
|
|
|
+
|
|
|
|
+ x, y = 2 * np.transpose(x, (0, 3, 1, 2)) - 1, np.transpose(y, (0, 3, 1, 2))
|
|
|
|
+ print x.shape, y.shape, np.amax(x), np.amin(x), np.amax(y), np.amin(y)
|
|
|
|
+ return x, y
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def make_val():
|
|
|
|
+ print "let's pick some samples for validation"
|
|
|
|
+ img = np.load('data/x_trn_%d.npy' % N_Cls)
|
|
|
|
+ msk = np.load('data/y_trn_%d.npy' % N_Cls)
|
|
|
|
+ x, y = get_patches(img, msk, amt=3000)
|
|
|
|
+
|
|
|
|
+ np.save('data/x_tmp_%d' % N_Cls, x)
|
|
|
|
+ np.save('data/y_tmp_%d' % N_Cls, y)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def get_unet():
|
|
|
|
+ inputs = Input((8, ISZ, ISZ))
|
|
|
|
+ conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(inputs)
|
|
|
|
+ conv1 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv1)
|
|
|
|
+ pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
|
|
|
|
+
|
|
|
|
+ conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(pool1)
|
|
|
|
+ conv2 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv2)
|
|
|
|
+ pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
|
|
|
|
+
|
|
|
|
+ conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(pool2)
|
|
|
|
+ conv3 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv3)
|
|
|
|
+ pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
|
|
|
|
+
|
|
|
|
+ conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(pool3)
|
|
|
|
+ conv4 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv4)
|
|
|
|
+ pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)
|
|
|
|
+
|
|
|
|
+ conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(pool4)
|
|
|
|
+ conv5 = Convolution2D(512, 3, 3, activation='relu', border_mode='same')(conv5)
|
|
|
|
+
|
|
|
|
+ up6 = merge([UpSampling2D(size=(2, 2))(conv5), conv4], mode='concat', concat_axis=1)
|
|
|
|
+ conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(up6)
|
|
|
|
+ conv6 = Convolution2D(256, 3, 3, activation='relu', border_mode='same')(conv6)
|
|
|
|
+
|
|
|
|
+ up7 = merge([UpSampling2D(size=(2, 2))(conv6), conv3], mode='concat', concat_axis=1)
|
|
|
|
+ conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(up7)
|
|
|
|
+ conv7 = Convolution2D(128, 3, 3, activation='relu', border_mode='same')(conv7)
|
|
|
|
+
|
|
|
|
+ up8 = merge([UpSampling2D(size=(2, 2))(conv7), conv2], mode='concat', concat_axis=1)
|
|
|
|
+ conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(up8)
|
|
|
|
+ conv8 = Convolution2D(64, 3, 3, activation='relu', border_mode='same')(conv8)
|
|
|
|
+
|
|
|
|
+ up9 = merge([UpSampling2D(size=(2, 2))(conv8), conv1], mode='concat', concat_axis=1)
|
|
|
|
+ conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(up9)
|
|
|
|
+ conv9 = Convolution2D(32, 3, 3, activation='relu', border_mode='same')(conv9)
|
|
|
|
+
|
|
|
|
+ conv10 = Convolution2D(N_Cls, 1, 1, activation='sigmoid')(conv9)
|
|
|
|
+
|
|
|
|
+ model = Model(input=inputs, output=conv10)
|
|
|
|
+ model.compile(optimizer=Adam(), loss='binary_crossentropy', metrics=[jaccard_coef, jaccard_coef_int, 'accuracy'])
|
|
|
|
+ return model
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def calc_jacc(model):
|
|
|
|
+ img = np.load('data/x_tmp_%d.npy' % N_Cls)
|
|
|
|
+ msk = np.load('data/y_tmp_%d.npy' % N_Cls)
|
|
|
|
+
|
|
|
|
+ prd = model.predict(img, batch_size=4)
|
|
|
|
+ print prd.shape, msk.shape
|
|
|
|
+ avg, trs = [], []
|
|
|
|
+
|
|
|
|
+ for i in range(N_Cls):
|
|
|
|
+ t_msk = msk[:, i, :, :]
|
|
|
|
+ t_prd = prd[:, i, :, :]
|
|
|
|
+ t_msk = t_msk.reshape(msk.shape[0] * msk.shape[2], msk.shape[3])
|
|
|
|
+ t_prd = t_prd.reshape(msk.shape[0] * msk.shape[2], msk.shape[3])
|
|
|
|
+
|
|
|
|
+ m, b_tr = 0, 0
|
|
|
|
+ for j in range(10):
|
|
|
|
+ tr = j / 10.0
|
|
|
|
+ pred_binary_mask = t_prd > tr
|
|
|
|
+
|
|
|
|
+ jk = jaccard_similarity_score(t_msk, pred_binary_mask)
|
|
|
|
+ if jk > m:
|
|
|
|
+ m = jk
|
|
|
|
+ b_tr = tr
|
|
|
|
+ print i, m, b_tr
|
|
|
|
+ avg.append(m)
|
|
|
|
+ trs.append(b_tr)
|
|
|
|
+
|
|
|
|
+ score = sum(avg) / 10.0
|
|
|
|
+ return score, trs
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def mask_for_polygons(polygons, im_size):
|
|
|
|
+ # __author__ = Konstantin Lopuhin
|
|
|
|
+ # https://www.kaggle.com/lopuhin/dstl-satellite-imagery-feature-detection/full-pipeline-demo-poly-pixels-ml-poly
|
|
|
|
+ img_mask = np.zeros(im_size, np.uint8)
|
|
|
|
+ if not polygons:
|
|
|
|
+ return img_mask
|
|
|
|
+ int_coords = lambda x: np.array(x).round().astype(np.int32)
|
|
|
|
+ exteriors = [int_coords(poly.exterior.coords) for poly in polygons]
|
|
|
|
+ interiors = [int_coords(pi.coords) for poly in polygons
|
|
|
|
+ for pi in poly.interiors]
|
|
|
|
+ cv2.fillPoly(img_mask, exteriors, 1)
|
|
|
|
+ cv2.fillPoly(img_mask, interiors, 0)
|
|
|
|
+ return img_mask
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def mask_to_polygons(mask, epsilon=5, min_area=1.):
|
|
|
|
+ # __author__ = Konstantin Lopuhin
|
|
|
|
+ # https://www.kaggle.com/lopuhin/dstl-satellite-imagery-feature-detection/full-pipeline-demo-poly-pixels-ml-poly
|
|
|
|
+
|
|
|
|
+ # first, find contours with cv2: it's much faster than shapely
|
|
|
|
+ image, contours, hierarchy = cv2.findContours(
|
|
|
|
+ ((mask == 1) * 255).astype(np.uint8),
|
|
|
|
+ cv2.RETR_CCOMP, cv2.CHAIN_APPROX_TC89_KCOS)
|
|
|
|
+ # create approximate contours to have reasonable submission size
|
|
|
|
+ approx_contours = [cv2.approxPolyDP(cnt, epsilon, True)
|
|
|
|
+ for cnt in contours]
|
|
|
|
+ if not contours:
|
|
|
|
+ return MultiPolygon()
|
|
|
|
+ # now messy stuff to associate parent and child contours
|
|
|
|
+ cnt_children = defaultdict(list)
|
|
|
|
+ child_contours = set()
|
|
|
|
+ assert hierarchy.shape[0] == 1
|
|
|
|
+ # http://docs.opencv.org/3.1.0/d9/d8b/tutorial_py_contours_hierarchy.html
|
|
|
|
+ for idx, (_, _, _, parent_idx) in enumerate(hierarchy[0]):
|
|
|
|
+ if parent_idx != -1:
|
|
|
|
+ child_contours.add(idx)
|
|
|
|
+ cnt_children[parent_idx].append(approx_contours[idx])
|
|
|
|
+ # create actual polygons filtering by area (removes artifacts)
|
|
|
|
+ all_polygons = []
|
|
|
|
+ for idx, cnt in enumerate(approx_contours):
|
|
|
|
+ if idx not in child_contours and cv2.contourArea(cnt) >= min_area:
|
|
|
|
+ assert cnt.shape[1] == 1
|
|
|
|
+ poly = Polygon(
|
|
|
|
+ shell=cnt[:, 0, :],
|
|
|
|
+ holes=[c[:, 0, :] for c in cnt_children.get(idx, [])
|
|
|
|
+ if cv2.contourArea(c) >= min_area])
|
|
|
|
+ all_polygons.append(poly)
|
|
|
|
+ # approximating polygons might have created invalid ones, fix them
|
|
|
|
+ all_polygons = MultiPolygon(all_polygons)
|
|
|
|
+ if not all_polygons.is_valid:
|
|
|
|
+ all_polygons = all_polygons.buffer(0)
|
|
|
|
+ # Sometimes buffer() converts a simple Multipolygon to just a Polygon,
|
|
|
|
+ # need to keep it a Multi throughout
|
|
|
|
+ if all_polygons.type == 'Polygon':
|
|
|
|
+ all_polygons = MultiPolygon([all_polygons])
|
|
|
|
+ return all_polygons
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def get_scalers(im_size, x_max, y_min):
|
|
|
|
+ # __author__ = Konstantin Lopuhin
|
|
|
|
+ # https://www.kaggle.com/lopuhin/dstl-satellite-imagery-feature-detection/full-pipeline-demo-poly-pixels-ml-poly
|
|
|
|
+ h, w = im_size # they are flipped so that mask_for_polygons works correctly
|
|
|
|
+ h, w = float(h), float(w)
|
|
|
|
+ w_ = 1.0 * w * (w / (w + 1))
|
|
|
|
+ h_ = 1.0 * h * (h / (h + 1))
|
|
|
|
+ return w_ / x_max, h_ / y_min
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def train_net():
|
|
|
|
+ print "start train net"
|
|
|
|
+ x_val, y_val = np.load('data/x_tmp_%d.npy' % N_Cls), np.load('data/y_tmp_%d.npy' % N_Cls)
|
|
|
|
+ img = np.load('data/x_trn_%d.npy' % N_Cls)
|
|
|
|
+ msk = np.load('data/y_trn_%d.npy' % N_Cls)
|
|
|
|
+
|
|
|
|
+ x_trn, y_trn = get_patches(img, msk)
|
|
|
|
+
|
|
|
|
+ model = get_unet()
|
|
|
|
+ model.load_weights('weights/unet_10_jk0.7878')
|
|
|
|
+ model_checkpoint = ModelCheckpoint('weights/unet_tmp.hdf5', monitor='loss', save_best_only=True)
|
|
|
|
+ for i in range(1):
|
|
|
|
+ model.fit(x_trn, y_trn, batch_size=64, nb_epoch=1, verbose=1, shuffle=True,
|
|
|
|
+ callbacks=[model_checkpoint], validation_data=(x_val, y_val))
|
|
|
|
+ del x_trn
|
|
|
|
+ del y_trn
|
|
|
|
+ x_trn, y_trn = get_patches(img, msk)
|
|
|
|
+ score, trs = calc_jacc(model)
|
|
|
|
+ print 'val jk', score
|
|
|
|
+ model.save_weights('weights/unet_10_jk%.4f' % score)
|
|
|
|
+
|
|
|
|
+ return model
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def predict_id(id, model, trs):
|
|
|
|
+ img = M(id)
|
|
|
|
+ x = stretch_n(img)
|
|
|
|
+
|
|
|
|
+ cnv = np.zeros((960, 960, 8)).astype(np.float32)
|
|
|
|
+ prd = np.zeros((N_Cls, 960, 960)).astype(np.float32)
|
|
|
|
+ cnv[:img.shape[0], :img.shape[1], :] = x
|
|
|
|
+
|
|
|
|
+ for i in range(0, 6):
|
|
|
|
+ line = []
|
|
|
|
+ for j in range(0, 6):
|
|
|
|
+ line.append(cnv[i * ISZ:(i + 1) * ISZ, j * ISZ:(j + 1) * ISZ])
|
|
|
|
+
|
|
|
|
+ x = 2 * np.transpose(line, (0, 3, 1, 2)) - 1
|
|
|
|
+ tmp = model.predict(x, batch_size=4)
|
|
|
|
+ for j in range(tmp.shape[0]):
|
|
|
|
+ prd[:, i * ISZ:(i + 1) * ISZ, j * ISZ:(j + 1) * ISZ] = tmp[j]
|
|
|
|
+
|
|
|
|
+ # trs = [0.4, 0.1, 0.4, 0.3, 0.3, 0.5, 0.3, 0.6, 0.1, 0.1]
|
|
|
|
+ for i in range(N_Cls):
|
|
|
|
+ prd[i] = prd[i] > trs[i]
|
|
|
|
+
|
|
|
|
+ return prd[:, :img.shape[0], :img.shape[1]]
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def predict_test(model, trs):
|
|
|
|
+ print "predict test"
|
|
|
|
+ for i, id in enumerate(sorted(set(SB['ImageId'].tolist()))):
|
|
|
|
+ msk = predict_id(id, model, trs)
|
|
|
|
+ np.save('msk/10_%s' % id, msk)
|
|
|
|
+ if i % 100 == 0: print i, id
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def make_submit():
|
|
|
|
+ print "make submission file"
|
|
|
|
+ df = pd.read_csv(os.path.join(inDir, 'sample_submission.csv'))
|
|
|
|
+ print df.head()
|
|
|
|
+ for idx, row in df.iterrows():
|
|
|
|
+ id = row[0]
|
|
|
|
+ kls = row[1] - 1
|
|
|
|
+
|
|
|
|
+ msk = np.load('msk/10_%s.npy' % id)[kls]
|
|
|
|
+ pred_polygons = mask_to_polygons(msk)
|
|
|
|
+ x_max = GS.loc[GS['ImageId'] == id, 'Xmax'].as_matrix()[0]
|
|
|
|
+ y_min = GS.loc[GS['ImageId'] == id, 'Ymin'].as_matrix()[0]
|
|
|
|
+
|
|
|
|
+ x_scaler, y_scaler = get_scalers(msk.shape, x_max, y_min)
|
|
|
|
+
|
|
|
|
+ scaled_pred_polygons = shapely.affinity.scale(pred_polygons, xfact=1.0 / x_scaler, yfact=1.0 / y_scaler,
|
|
|
|
+ origin=(0, 0, 0))
|
|
|
|
+
|
|
|
|
+ df.iloc[idx, 2] = shapely.wkt.dumps(scaled_pred_polygons)
|
|
|
|
+ if idx % 100 == 0: print idx
|
|
|
|
+ print df.head()
|
|
|
|
+ df.to_csv('subm/1.csv', index=False)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+def check_predict(id='6120_2_3'):
|
|
|
|
+ model = get_unet()
|
|
|
|
+ model.load_weights('weights/unet_10_jk0.7878')
|
|
|
|
+
|
|
|
|
+ msk = predict_id(id, model, [0.4, 0.1, 0.4, 0.3, 0.3, 0.5, 0.3, 0.6, 0.1, 0.1])
|
|
|
|
+ img = M(id)
|
|
|
|
+
|
|
|
|
+ plt.figure()
|
|
|
|
+ ax1 = plt.subplot(131)
|
|
|
|
+ ax1.set_title('image ID:6120_2_3')
|
|
|
|
+ ax1.imshow(img[:, :, 5], cmap=plt.get_cmap('gist_ncar'))
|
|
|
|
+ ax2 = plt.subplot(132)
|
|
|
|
+ ax2.set_title('predict bldg pixels')
|
|
|
|
+ ax2.imshow(msk[0], cmap=plt.get_cmap('gray'))
|
|
|
|
+ ax3 = plt.subplot(133)
|
|
|
|
+ ax3.set_title('predict bldg polygones')
|
|
|
|
+ ax3.imshow(mask_for_polygons(mask_to_polygons(msk[0], epsilon=1), img.shape[:2]), cmap=plt.get_cmap('gray'))
|
|
|
|
+
|
|
|
|
+ plt.show()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
+ stick_all_train()
|
|
|
|
+ make_val()
|
|
|
|
+ model = train_net()
|
|
|
|
+ score, trs = calc_jacc(model)
|
|
|
|
+ predict_test(model, trs)
|
|
|
|
+ make_submit()
|
|
|
|
+
|
|
|
|
+ # bonus
|
|
|
|
+ check_predict()
|