{"cells":[{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","collapsed":true,"trusted":false},"cell_type":"code","source":"import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport glob\nimport os\nimport cv2\nfrom skimage import color\nfrom skimage import io\nimport tensorflow as tf\nimport tflearn\nfrom tflearn.layers.core import input_data, dropout, fully_connected\nfrom tflearn.layers.conv import conv_2d, max_pool_2d\nfrom tflearn.layers.normalization import local_response_normalization\nfrom tflearn.layers.estimator import regression\nfrom tflearn.data_preprocessing import ImagePreprocessing\nfrom tflearn.data_augmentation import ImageAugmentation\nfrom tflearn.metrics import Accuracy\nimport random\nimport csv as csv\nimport numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline \n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"fbb3039c333698c020e5711181ae207496a79088"},"cell_type":"markdown","source":"# Train a dog-cat classifier"},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"trusted":false},"cell_type":"code","source":"TRAIN_DIR = '../input/train/'\nTEST_DIR = '../input/test/'\n\nIMG_SIZE = 50 #image size 50x50\ndef read_image(file_path):        \n    img= cv2.imread(file_path, cv2.IMREAD_GRAYSCALE)\n    img= cv2.resize(img, (IMG_SIZE, IMG_SIZE), interpolation=cv2.INTER_CUBIC)\n    return img\n\ndef prep_data(images):\n    count = len(images)\n    data = np.ndarray((count, IMG_SIZE, IMG_SIZE, 1), dtype=np.uint8)\n\n    for i, image_file in enumerate(images):\n        image = read_image(image_file)\n        data[i] = image.reshape(-1, IMG_SIZE, IMG_SIZE, 1)\n        if i%5000 == 0: print('Processed {} of {}'.format(i, count))\n    \n    return data\n\ntrain_cats = sorted(glob.glob(os.path.join(TRAIN_DIR, 'cat*.jpg')))\ntrain_dogs = sorted(glob.glob(os.path.join(TRAIN_DIR, 'dog*.jpg')))\ntrain_all = train_dogs+train_cats \n\nrandom.Random(4).shuffle(train_all)\n\ntest_all = sorted(glob.glob(os.path.join(TEST_DIR, '*.jpg')))\n\n#X变成矩阵形式，Y变成0/1向量形式\nX_train = prep_data([path for path in train_all])\nY_train = np.array([[1., 0.] if 'dog' in name else [0., 1.] for name in train_all])\n\nX_test = prep_data([path for path in test_all])\nY_test = np.array([[1., 0.] if 'dog' in name else [0., 1.] for name in test_all])","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"84fa448bc0245182185144a27fe462909cdd040f","collapsed":true,"trusted":false},"cell_type":"code","source":"#定义神经网络，None---batch size大小不固定，IMG_SIZE--固定，1---图像通道数（灰度图显示，没有彩色图片）\n#feature map的数量一步步变多，又一步步变少（32-64-128-64-32）\nconvnet = input_data(shape=[None, IMG_SIZE, IMG_SIZE, 1], name='input')\n#第二层对前一个input做卷积（32个不同的5x5卷积），卷积的结果会通过relu凼数激活\n#这里没有padding, 其实卷积是可以padding的\nconvnet = conv_2d(convnet, 32, 5, activation='relu')\nconvnet = max_pool_2d(convnet, 5)#卷积之后做5x5的max pooling\nconvnet = conv_2d(convnet, 64, 5, activation='relu')\nconvnet = max_pool_2d(convnet, 5)\nconvnet = conv_2d(convnet, 128, 5, activation='relu')\nconvnet = max_pool_2d(convnet, 5)\nconvnet = conv_2d(convnet, 64, 5, activation='relu')\nconvnet = max_pool_2d(convnet, 5)\nconvnet = conv_2d(convnet, 32, 5, activation='relu')\nconvnet = max_pool_2d(convnet, 5)\n#最后一层卷积做完后加入全连接（大小是1024）\nconvnet = fully_connected(convnet, 1024, activation='relu')\nconvnet = dropout(convnet, 0.8) #随机丢20%的参数\nconvnet = fully_connected(convnet, 2, activation='softmax') #再使用全连接\n#train model\nconvnet = regression(convnet, optimizer='adam', learning_rate=0.001, loss='categorical_crossentropy', name='targets')\n\n#用DNN(深度神经网络)来fit这个model\nmodel = tflearn.DNN(convnet, tensorboard_dir='log')\nmodel.fit({'input': X_train}, {'targets': Y_train}, n_epoch=3, validation_set=({'input': X_test}, {'targets': Y_test}), \n    snapshot_step=500, show_metric=True, run_id='dog-cat')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b085579e3cf84d943d00637f6f222cff7c48cc17"},"cell_type":"markdown","source":"# Run inference"},{"metadata":{"_uuid":"80883f822c0b7af6039ed59b4f499720c6380b82","collapsed":true,"trusted":false},"cell_type":"code","source":"def pyramid(image, scale=1.5, minSize=(30, 30)): #图像金字塔\n    # yield the original image\n    yield image\n    \n    # keep looping over the pyramid\n    while True:\n        # compute the new dimensions of the image and resize it\n        w = int(image.shape[1] / scale)#不停地缩小这张图\n        h = int(image.shape[0] / scale)\n        image = cv2.resize(image, (w, h))\n\n        # if the resized image does not meet the supplied minimum\n        # size, then stop constructing the pyramid\n        if image.shape[0] < minSize[1] or image.shape[1] < minSize[0]:\n            break\n\n        # yield the next image in the pyramid\n        yield image\n        \ndef sliding_window(image, stepSize, windowSize): #怎么找sliding_window的四个大小\n    for y in range(0, image.shape[0] - windowSize[1], stepSize):\n        for x in range(0, image.shape[1] - windowSize[0], stepSize):\n            # yield the current window\n            yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])\n\ndef get_grey_and_color_image(path): #把灰度图和彩色图都显示出来\n    return cv2.imread(path), cv2.imread(path, cv2.IMREAD_GRAYSCALE)\n            \ndef run_inference(image):\n    (w, h) = (50, 50)\n    # loop over the image pyramid\n    scale = 1.\n    cats_score = []\n    cats_bbox = []\n    dogs_score = []\n    dogs_bbox = []\n    for resized in pyramid(image, scale=1.5): #先枚举所有不同大小的图片\n        # loop over the sliding window for each layer of the pyramid\n        for (x, y, window) in sliding_window(resized, stepSize=32, windowSize=(w, h)):\n            input_data = np.ndarray((1, IMG_SIZE, IMG_SIZE, 1), dtype=np.uint8)\n            input_data[0] = window.reshape(-1, IMG_SIZE, IMG_SIZE, 1)\n            out = model.predict(input_data)[0]\n\n            if np.argmax(out) == 1:\n                if out[1] > 0.8:#选出来的score一定会大于0.8\n                    cats_score.append(out[1])\n                    cats_bbox.append((int(x * scale), int(y * scale), int(w * scale), int(h * scale)))\n            else:\n                if out[0] > 0.8:\n                    dogs_score.append(out[0])\n                    dogs_bbox.append((int(x * scale), int(y * scale), int(w * scale), int(h * scale)))\n\n        scale = scale * 1.5\n        #输出是猫的score和bbox和是狗的score和bbox\n    return cats_score, cats_bbox, dogs_score, dogs_bbox","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e90af544b693eae16ae3532939d517f5030b2cfd","collapsed":true,"trusted":false},"cell_type":"code","source":"#可视化是猫的score和bbox和是狗的score和bbox\n#这里没有用RCN的selective search, 用图像金字塔和sliding window解决的问题\ndef showWindows(image, dogs_bbox, cats_bbox):\n    for (x, y, w, h) in dogs_bbox:\n        cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)\n    for (x, y, w, h) in cats_bbox:\n        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)\n    plt.imshow(np.array(image).astype('uint8'))\n    plt.show()\n    \nTHRESHOLD = 0.2\ndef nms(scores, bboxes):#score和bounding box一一对应的\n    #先排序（从高到低），把所有的score和bounding box都拿出来\n    sortedRes = sorted(zip(scores, bboxes), key = lambda x: x[0], reverse=True)\n    scores = [score for (score, bbox) in sortedRes]\n    bboxes = [bbox for (score, bbox) in sortedRes]\n    \n    suppress = [0] * len(scores)\n    result = []\n    for i in range(len(bboxes)): #枚举所有的bounding box\n        if suppress[i] == 1: #先判断bounding box有没有被删除\n            continue\n        \n        #如果没被删除，计算下并集和交集，再相除下\n        area = bboxes[i][2] * bboxes[i][3] #选择的bounding box的面积是多少\n        result.append(bboxes[i]) #把这个设置为框A（ppt32）\n        for j in range(i+1, len(bboxes)): #枚举到的另一个框（B），如果IOU比较大，就把框B删除\n            if suppress[j] == 1:\n                continue\n            \n            otherArea = bboxes[j][2] * bboxes[i][3] #枚举到的另一个框的大小，并且算下它和框A的交集\n            xx1 = np.maximum(bboxes[i][0], bboxes[j][0])\n            yy1 = np.maximum(bboxes[i][1], bboxes[j][1])\n            xx2 = np.minimum(bboxes[i][0] + bboxes[i][2] - 1, bboxes[j][0] + bboxes[j][2] - 1)\n            yy2 = np.minimum(bboxes[i][1] + bboxes[i][3] - 1, bboxes[j][1] + bboxes[j][3] - 1)\n            \n            w = np.maximum(0.0, xx2 - xx1 + 1)\n            h = np.maximum(0.0, yy2 - yy1 + 1)\n            inter = w * h #交集的大小\n            ovr = inter / min(area,otherArea) #IOU #除以并集或者是两个框的最小值\n            if ovr > THRESHOLD:\n                suppress[j] = 1  #如果> THRESHOLD，就把框B删除\n    return result","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"08f7127b6af8ce9f53fa79c16c039b0ad131f57b","collapsed":true,"trusted":false},"cell_type":"code","source":"color_image, image = get_grey_and_color_image(test_all[1])\ncats_score, cats_bbox, dogs_score, dogs_bbox = run_inference(image)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"b556760dff857972038119adffe827f950d86cba","collapsed":true,"trusted":false},"cell_type":"code","source":"showWindows(color_image.copy(), dogs_bbox, cats_bbox)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"10507c93d2402ae945717cd014e80396e049563f","collapsed":true,"trusted":false},"cell_type":"code","source":"new_dogs_bboxes = nms(dogs_score, dogs_bbox)\nnew_cats_bboxes = nms(cats_score, cats_bbox)\nshowWindows(color_image.copy(), new_dogs_bboxes, new_cats_bboxes)","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.6","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}