{"cells":[{"metadata":{"_cell_guid":"d304b92d-60db-48c3-8237-e66d86afb9b4","_uuid":"69231124cb006aae356154f7a34411645374a0eb"},"cell_type":"markdown","source":"# Overview\nThe script applies OpenCV-based detection to all the images to provide a basic baseline for pedestrian detection. The code is based loosely off of https://github.com/opencv/opencv/blob/master/samples/python/peopledetect.py"},{"metadata":{"collapsed":true,"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","trusted":false},"cell_type":"code","source":"%matplotlib inline\nimport os\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom glob import glob\nimport matplotlib.pyplot as plt\nfrom skimage.io import imread\nfrom skimage.segmentation import mark_boundaries\nimport cv2\nDATA_DIR = os.path.join('..', 'input')","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":false},"cell_type":"code","source":"class_str = \"\"\"car, 33\nmotorbicycle, 34\nbicycle, 35\nperson, 36\nrider, 37\ntruck, 38\nbus, 39\ntricycle, 40\nothers, 0\nrover, 1\nsky, 17\ncar_groups, 161\nmotorbicycle_group, 162\nbicycle_group, 163\nperson_group, 164\nrider_group, 165\ntruck_group, 166\nbus_group, 167\ntricycle_group, 168\nroad, 49\nsiderwalk, 50\ntraffic_cone, 65\nroad_pile, 66\nfence, 67\ntraffic_light, 81\npole, 82\ntraffic_sign, 83\nwall, 84\ndustbin, 85\nbillboard, 86\nbuilding, 97\nbridge, 98\ntunnel, 99\noverpass, 100\nvegatation, 113\nunlabeled, 255\"\"\"\nclass_dict = {v.split(', ')[0]: int(v.split(', ')[-1]) for v in class_str.split('\\n')}","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"6098a265-8f65-4b09-aa14-c0906ba06776","_uuid":"25cc2323ae74135f3150e1a044c4a3ce967a274b","trusted":false,"collapsed":true},"cell_type":"code","source":"all_paths = pd.DataFrame(dict(path = glob(os.path.join(DATA_DIR, '*', '*.*p*g'))))\nclassdict = {0:'others', 1:'rover', 17:'sky', 33:'car', 34:'motorbicycle', 35:'bicycle', 36:'person', 37:'rider', 38:'truck', 39:'bus', 40:'tricycle', 49:'road', 50:'siderwalk', 65:'traffic_cone'}\nall_paths['split'] = all_paths['path'].map(lambda x: x.split('/')[-2].split('_')[0])\nall_paths['group'] = all_paths['path'].map(lambda x: x.split('/')[-2].split('_')[-1])\nall_paths['group'] = all_paths['group'].map(lambda x: 'color' if x == 'test' else x)\nall_paths['id'] = all_paths['path'].map(lambda x: '_'.join(os.path.splitext(os.path.basename(x))[0].split('_')[:4]))\nall_paths.sample(5)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"d18ebca1-7a33-4358-9557-9b324b549f60","_uuid":"0bc5a92bfa970cfd251c6f6619f723161e42d87f","trusted":false,"collapsed":true},"cell_type":"code","source":"group_df = all_paths.pivot_table(values = 'path', columns = 'group', aggfunc = 'first', index = ['id', 'split']).reset_index()\ngroup_df.sample(5)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"c70b0455-b190-4b7d-8521-b8ce227e4885","_uuid":"9a6b25b8261b815e7b8237e1b9e101c512c4a85b"},"cell_type":"markdown","source":"# Build up a set of classifiers\nHere we make a dictionary of classifiers using the HaarCascades as a basis. The person detector probably works best so we will stick to that one, but there are a number of pre-trained cascading classifiers and HOG classifiers that could be easily added to cover other classes."},{"metadata":{"collapsed":true,"_cell_guid":"44f3fd88-03e3-49cb-b8e3-8c88af672715","_uuid":"31b1e734550c6cd48c70954365f0b19d9a5d3649","trusted":false},"cell_type":"code","source":"classifiers = {}\ndef inside(r, q):\n    rx, ry, rw, rh = r\n    qx, qy, qw, qh = q\n    return rx > qx and ry > qy and rx + rw < qx + qw and ry + rh < qy + qh\n\nclass PersonDetector():\n    def __init__(self):\n        # make it picklable\n        self.hog = cv2.HOGDescriptor()\n        self.hog.setSVMDetector( cv2.HOGDescriptor_getDefaultPeopleDetector() )\n    def detect(self, gray_img, run_filter):\n        c_found, _ = self.hog.detectMultiScale(gray_img, winStride=(8,8), padding=(32,32), scale=1.05)\n        if run_filter:\n            for ri, r in enumerate(c_found):\n                for qi, q in enumerate(c_found):\n                    if ri != qi and inside(r, q):\n                        break\n                else:\n                    found_filtered.append(r)\n            return found_filtered.tolist()\n        else:\n            try:\n                return c_found.tolist()\n            except AttributeError:\n                # sometimes opencv returns empty tuples\n                return []\n        \nclassifiers['person'] = PersonDetector()","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"9228f651-c60a-4b3a-b051-805c53c8be1e","_uuid":"6f9cc89c5c608a07775659cfbf047c36796b5e52","trusted":false,"collapsed":true},"cell_type":"code","source":"# ensure empty case works well\nPersonDetector().detect(np.zeros((128, 128), dtype = np.uint8), False)","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"1bec555b-2e42-4a83-b097-425193f685aa","_uuid":"f2e6452273b5c238eb31060c4de8be1cb92b70f1","trusted":false},"cell_type":"code","source":"def apply_classifier(in_path, all_classes, run_filter = False, debug_mode = False):\n    im = cv2.imread(in_path)\n    gr_im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)\n    out_segs = np.zeros(gr_im.shape, dtype = np.uint16)\n    found = []\n    for c_label, c_class in all_classes.items():\n        c_found = c_class.detect(gr_im, run_filter = run_filter)\n        found += c_found\n        thickness = 4\n        for i, (x, y, w, h) in enumerate(c_found):\n            # the HOG detector returns slightly larger rectangles than the real objects.\n            # so we slightly shrink the rectangles to get a nicer output.\n            pad_w, pad_h = int(0.15*w), int(0.05*h)\n            if debug_mode:\n                cv2.rectangle(im, (x+pad_w, y+pad_h), (x+w-pad_w, y+h-pad_h), (0, 255, 0), thickness)\n            out_segs[(y+pad_h):(y+h-pad_h), (x+pad_w):(x+w-pad_w)] = class_dict[c_label]*1000+i\n    if debug_mode:\n        return cv2.cvtColor(im, cv2.COLOR_BGR2RGB), out_segs\n    else:\n        return out_segs","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"9f174410-560f-447d-a4ee-157534b1ee8a","_uuid":"e60726db98e6023fb1a25636a919c2b4da3b6dc3","trusted":false,"collapsed":true},"cell_type":"code","source":"test_path = '../input/train_color/171206_033232166_Camera_5.jpg'\nnrm_img, _ = apply_classifier(test_path, {}, debug_mode = True)\n%timeit _ = apply_classifier(test_path, classifiers, debug_mode = False)\ncls_img, seg_img = apply_classifier(test_path, classifiers, debug_mode = True)\nfig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize = (20, 8))\nax1.imshow(nrm_img)\nax2.imshow(cls_img[1501:1963, 844:1936])\nax2.set_title('Person Detection ({})'.format(len(np.unique(seg_img))-1));\nax3.imshow(seg_img[1501:1963, 844:1936])\nax3.set_title('Segment Output');","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"54a50a97-f755-4616-a686-e331be74cdc9","_uuid":"210a695c0ffb9545d179ad1dd9d6280336d686e5"},"cell_type":"markdown","source":"# Test on Random Images"},{"metadata":{"_cell_guid":"3ee6260e-1115-49a5-9ad7-ed39bb78bbe4","_uuid":"cb96ad7d86632143b5c212f94369afa3ee1247e1","trusted":false,"collapsed":true},"cell_type":"code","source":"train_df = group_df.query('split==\"train\"')\nprint(train_df.shape[0], 'rows')\nsample_rows = 10\nfig, m_axs = plt.subplots(sample_rows, 5, figsize = (20, 6*sample_rows))\n[c_ax.axis('off') for c_ax in m_axs.flatten()]\nout_rows = []\nfor (ax1, ax2, ax4, ax3, ax_c_crop), (_, c_row) in zip(m_axs, train_df.sample(sample_rows, random_state = 2018).iterrows()):\n    c_img = imread(c_row['color'])\n    l_img = imread(c_row['label'])//1000\n    seg_img = apply_classifier(c_row['color'], classifiers)\n    ax1.imshow(c_img)\n    ax1.set_title('Color')\n    ax2.imshow(l_img, cmap = 'nipy_spectral')\n    ax2.set_title('Segments')\n    xd, yd = np.where(l_img>0)\n    bound_img = mark_boundaries(image = c_img, label_img = l_img, color = (1,0,0), background_label = 255, mode = 'thick')\n    ax3.imshow(bound_img[xd.min():xd.max(), yd.min():yd.max(),:])\n    ax3.set_title('Cropped Overlay')\n    ax4.imshow(cls_img)\n    ax4.set_title('HOG Image %d objects\\n Accuracy: %2.3f%%\\n Non-zero Accuracy %2.2f%%' % (np.max(seg_img) % 1000, \n                                                                                            100*np.mean((l_img>0)==(seg_img>0)),\n                                                                                           100*np.mean((seg_img[l_img>0]>0))))\n    ax_c_crop.imshow(seg_img[xd.min():xd.max(), yd.min():yd.max()])\n    ax_c_crop.set_title('Cropped HOG')\nfig.savefig('sample_overview.png')","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"7a390ec3-ba65-4933-b868-aeabc36f2487","_uuid":"1c4f043ef2b22909957e2b767960f13b656304fb","trusted":false,"collapsed":true},"cell_type":"code","source":"test_df = group_df.query('split==\"test\"').drop(['label'], axis = 1)\nprint(test_df.shape[0], 'rows')\ntest_df.sample(3)","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"3555d35b-afc3-436c-8a9f-113b4cb60915","_uuid":"1d88f9779e0a90703b2c887f864b057945d18292","trusted":false},"cell_type":"code","source":"def rle_encoding(x):\n    \"\"\" Run-length encoding based on\n    https://www.kaggle.com/rakhlin/fast-run-length-encoding-python\n    Modified by Konstantin, https://www.kaggle.com/lopuhin\n    \"\"\"\n    assert x.dtype == np.bool\n    dots = np.where(x.flatten() == 1)[0]\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if b > prev + 1:\n            run_lengths.append([b, 0])\n        run_lengths[-1][1] += 1\n        prev = b\n    return '|'.join('{} {}'.format(*pair) for pair in run_lengths)\n\ndef segs_to_rle_rows(lab_img, **kwargs):\n    out_rows = []\n    for i in np.unique(lab_img[lab_img>0]):\n        c_dict = dict(**kwargs)\n        c_dict['LabelId'] = i//1000\n        c_dict['PixelCount'] = np.sum(lab_img==i)\n        c_dict['Confidence'] = 0.5 # our classifier isnt very good so lets not put the confidence too high\n        c_dict['EncodedPixels'] = rle_encoding(lab_img==i)\n        out_rows += [c_dict]\n    return out_rows","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"f15a839a-839c-45bb-b917-9cb653186f25","_uuid":"c60976f2d4c71c747f1a3dc233a85015519463b5","trusted":false,"collapsed":true},"cell_type":"code","source":"# make sure it works on a simple case\npd.DataFrame(segs_to_rle_rows(seg_img, ImageId = -1))","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"e63ebe95-1406-4b2b-9cad-9d80412aafba","_uuid":"e0cde8d49895dd83b49979d1856682c03a948c3d"},"cell_type":"markdown","source":"# Create overview for all images\nWe want to create this overview for all images, but to do it serially takes too long"},{"metadata":{"collapsed":true,"_cell_guid":"15444f03-f611-4b2c-b3b2-d33e712970b6","_uuid":"b12ea9ec752316f17f456228488aa1f1b2b425e2","trusted":false},"cell_type":"code","source":"def read_row(in_row):\n    c_segs = apply_classifier(in_row['color'], classifiers)\n    return segs_to_rle_rows(c_segs, ImageId = in_row['id'])","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"95cb6abc-0e33-464e-9a3b-55779a1a3ef8","_uuid":"27ca6c88c9b8c018c28de0195bf4979864ae9724"},"cell_type":"markdown","source":"# Small Sample\nHere we do a small sub-sample to see how long it will take and ensure everything works correctly."},{"metadata":{"_cell_guid":"d7072ee5-060f-420a-a5ca-ab23056b3960","_uuid":"7e5bcffabc67225549f4c94d76a5d3170c40013f","trusted":false,"collapsed":true},"cell_type":"code","source":"%%time\nfrom tqdm import tqdm_notebook\nall_rows = []\nfor _, c_row in tqdm_notebook(list(test_df.sample(10).iterrows())):\n    all_rows += read_row(c_row.to_dict())","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"204c0d90-46a0-4fd9-8f2e-64de4611d12d","_uuid":"cb09126f225a630a7c3d73b4d4ab78e35b94d489","trusted":false},"cell_type":"code","source":"%%time\nall_rows = []\nfor _, c_row in tqdm_notebook(list(test_df.iterrows())):\n    all_rows += read_row(c_row.to_dict())","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"0ec73e1d-1613-4af9-bbe3-ca00c084d9d8","_uuid":"25a2c2062e68c7800c16f0cdddca24ab835eb73f","trusted":false},"cell_type":"code","source":"all_rows_df = pd.DataFrame(all_rows)\nall_rows_df = all_rows_df[['ImageId', 'LabelId', 'PixelCount', 'Confidence', 'EncodedPixels']]\nall_rows_df.to_csv('opencv_full_submission.csv', index = False)\nall_rows_df.sample(5)","execution_count":null,"outputs":[]},{"metadata":{"collapsed":true,"_cell_guid":"96608d35-9edf-4e22-b199-1e0cfba57555","_uuid":"1bc7bce6e9c56d98a72fa84d660bfbfbe3fbb990","trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"language_info":{"name":"python","version":"3.6.5","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"}},"nbformat":4,"nbformat_minor":1}