{"cells":[{"metadata":{"_uuid":"3b1ea2a685bd741f3fba673add731fdb64cb5d19"},"cell_type":"markdown","source":"## Library input"},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import cv2\nimport math\nimport random\nimport ast\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"# draw image function\ndef draw_cv2(raw_strokes, base_size = 256, img_size=128, lw=6, time_color=True):\n    img = np.zeros((base_size, base_size), np.uint8)\n    for t, stroke in enumerate(raw_strokes):\n        for i in range(len(stroke[0]) - 1):\n            color = 255 - min(t, 10) * 13 if time_color else 255\n            _ = cv2.line(img, (stroke[0][i], stroke[1][i]), (stroke[0][i + 1], stroke[1][i + 1]), color, lw)\n    if img_size != base_size:\n        return cv2.resize(img, (img_size, img_size))\n    else:\n        return img   ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"d00619b09e3c4e8548c3fdeeade9b8ce2acea2a9"},"cell_type":"code","source":"# read test file\ntest = pd.read_csv('../input/test_simplified.csv')","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"e58f4fb8c25cd2703372cc86e5442a4c0d82f88a"},"cell_type":"markdown","source":"## Show Original Image"},{"metadata":{"trusted":true,"_uuid":"e8d1d62df829879c0004ad97360e56380c6df6db"},"cell_type":"code","source":"# choose a random image\ni = test[test['key_id'] == 9000052667981386].iloc[0]['drawing']\nimg = draw_cv2(ast.literal_eval(i),img_size=256)\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"66715e9bc06211013dc97d2eee5b329e0fc22d06"},"cell_type":"markdown","source":"## Local deformation\n\nThe whole image consists of many strokes sequences, let's deform each local stroke.\nFirst we have to calculate the ratio between the line distance of start/end point and the curve distance of stroke, to generate a Gaussian distribution standard variance. Then we sample from this Gaussian distribution to generate the coordinate disturbance in stroke points sequence."},{"metadata":{"trusted":true,"_uuid":"cb6ad2d30f316a703bf9c2e8fbfd542988c55b0d"},"cell_type":"code","source":"# deform one stroke in a whole image\n# scale is pre-defined constant\ndef deform_single_line(line, scale = 10, eps = 0.00001):\n    x,y = line[0], line[1]\n    \n    # get start and end point x/y\n    x_pre, y_pre = x[0],y[0]\n    x_end, y_end = x[-1],y[-1]\n    \n    # line distance between start point & end point\n    l_dis = math.sqrt((x_pre-x_end)**2 + (y_pre-y_end)**2)\n    \n    curve_dis = 0\n    for idx in range(len(x)-1):\n        sx,sy = x[idx],y[idx]\n        ex,ey = x[idx+1],y[idx+1]\n        \n        curve_dis += math.sqrt((sx-ex)**2 + (sy-ey)**2)\n\n    # ratio between line distance and curve distance\n    ratio = float(l_dis)/(curve_dis+eps)\n    if ratio > 1:\n        return [x,y]\n    \n    # disturbance direction\n    r1 = (random.uniform(0,1)<=0.5)*2-1\n    r2 = (random.uniform(0,1)<=0.5)*2-1\n    res_x,res_y = x.copy(),y.copy()\n    \n    for idx in range(1,len(x)-1):\n        \n        # a little move\n        res_x[idx] += int(scale*r1*ratio*abs(np.random.randn()))\n        res_y[idx] += int(scale*r2*ratio*abs(np.random.randn()))\n        \n    res_line = [res_x, res_y]\n    return res_line\n\n# deform whole image by deform each strokes\ndef local_deform(lines):\n    res = []\n    for line in lines:\n        res.append(deform_single_line(line))\n    return res\n            \ndef scatter_line(line, base_size = 256, c ='b'):\n    x,y = line[0], line[1]\n    for idx,ele in enumerate(y):\n        y[idx] = base_size - ele\n    plt.scatter(x, y, c = c)\n    plt.xlim(0,base_size)\n    plt.ylim(0,base_size)\n","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"ed04f8b3088e2927cab93a60e08fac7c579f65a0"},"cell_type":"markdown","source":"## One stroke"},{"metadata":{"trusted":true,"_uuid":"0b04caddfb5db2ea36ba8331edd3eeb2602fd79e"},"cell_type":"code","source":"before_ = ast.literal_eval(i)[0]\nafter_ = deform_single_line((ast.literal_eval(i)[0]))\n\nscatter_line(before_,c = 'b')\nscatter_line(after_,c = 'r')\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"3745b939366c6db62f4d4af9396ad138179bc9cb"},"cell_type":"markdown","source":"we apply local deformation to blue point, then generate the deform result(red point)"},{"metadata":{"_uuid":"29e101fb1dd8fecd97dd18521a9d7edfe0380dd4"},"cell_type":"markdown","source":"## Whole Image Local Deformation"},{"metadata":{"trusted":true,"_uuid":"fda420f3ba4a5137af44a48d845d114f9c9ee0a4"},"cell_type":"code","source":"img = draw_cv2(local_deform(ast.literal_eval(i)),img_size=256)\nplt.imshow(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_uuid":"110dce76424af0fa0a960397599b5be34a4c03de"},"cell_type":"code","source":"","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}