diff --git a/.ipynb_checkpoints/openCV_scanner-checkpoint.ipynb b/.ipynb_checkpoints/openCV_scanner-checkpoint.ipynb
index 313abaf19e2933cc1ffc3d469befa6dd80f71245..0078e221a9b5fdb46c4f542687f327c57698b6fc 100644
--- a/.ipynb_checkpoints/openCV_scanner-checkpoint.ipynb
+++ b/.ipynb_checkpoints/openCV_scanner-checkpoint.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 301,
+   "execution_count": 176,
    "metadata": {
     "scrolled": true
    },
@@ -20,90 +20,119 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 302,
+   "execution_count": 177,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def findMaxArea(contours):  \n",
-    "    max_area = -1\n",
-    "    max_index = -1\n",
-    "    for i,contour in enumerate(contours):\n",
-    "        area = cv2.contourArea(contour)\n",
-    "        x,y,w,h = cv2.boundingRect(contour)\n",
-    "        if (w*h)*0.4 > area:\n",
-    "            continue\n",
-    "        if w > h:\n",
-    "            continue\n",
-    "        if area > max_area:\n",
-    "            max_area = area\n",
-    "            max_index = i\n",
-    "    if max_area < 10000:\n",
-    "        max_index = -1\n",
-    "    return max_index"
+    "# 두 점 사이의 거리를 구한다.\n",
+    "# param : point1, point2 - 거리를 구할 두 점이다.\n",
+    "# return : point1, point2 사이의 거리이다.\n",
+    "def distance(point1, point2):\n",
+    "    \n",
+    "    x1,y1 = point1\n",
+    "    x2,y2 = point2\n",
+    " \n",
+    "    return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 303,
+   "execution_count": 178,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def transform(img_input, points):\n",
-    "    # 다음 순서롤 갖도록 꼭지점을 정렬한다.\n",
-    "    # top left, top right, bottom right, bottom left\n",
-    "    points = sort_points(points)\n",
-    "    topLeft, topRight, bottomRight, bottomLeft = points\n",
-    "    print(topLeft, topRight, bottomRight, bottomLeft)\n",
-    "    print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],\n",
-    "     bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])\n",
-    " \n",
-    "    # 변환 후 책의 너비와 높이를 결정한다.\n",
-    "    topWidth = distance(bottomLeft, bottomRight)\n",
-    "    bottomWidth = distance(topLeft, topRight)\n",
-    "    maxWidth = max(int(topWidth), int(bottomWidth))\n",
-    " \n",
-    "    leftHeight = distance(topLeft, bottomLeft)\n",
-    "    rightHeight = distance(topRight, bottomRight)\n",
-    "    maxHeight = max(int(leftHeight), int(rightHeight))\n",
-    " \n",
-    "    # 정면에서 바라본 책의 좌표를 결정한다.\n",
-    "    dst = np.array([[0, 0],[maxWidth - 1, 0],\n",
-    "        [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = \"float32\")\n",
-    " \n",
-    "    H = cv2.getPerspectiveTransform(points, dst)\n",
-    "    img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))\n",
-    " \n",
-    "    return img_warped\n"
+    "# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.\n",
+    "# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다, \n",
+    "#         flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,\n",
+    "#         param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.\n",
+    "# return : none\n",
+    "def mouse_callback(event,x,y,flags,param):\n",
+    "    \n",
+    "    global mouse_is_pressing, points\n",
+    "    # step == 1 이면,마우스 콜백 함수가 등록된 것이다.\n",
+    "    # step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.\n",
+    "    if step != 1:\n",
+    "        return\n",
+    "    \n",
+    "    # CASE 1 - 마우스가 움직이고\n",
+    "    if event == cv2.EVENT_MOUSEMOVE: \n",
+    "        # 눌린상태일때\n",
+    "        if mouse_is_pressing == True:\n",
+    "                    points[i][0] = x             \n",
+    "            #마우스의  좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다\n",
+    "            for i,point in enumerate(points):\n",
+    "                if distance((x,y), point) < 15:  \n",
+    "                    points[i][0] = x             \n",
+    "                    points[i][1] = y\n",
+    "                    break    \n",
+    "    # CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때,      \n",
+    "    elif event == cv2.EVENT_LBUTTONDOWN:\n",
+    "        # 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.                                          ##press 를 Ture로 바꾼다.\n",
+    "        for point in points:\n",
+    "            if distance((x,y), point) < 10:\n",
+    "                mouse_is_pressing = True\n",
+    "                break\n",
+    "    # CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈\n",
+    "    elif event == cv2.EVENT_LBUTTONUP:\n",
+    "\n",
+    "        mouse_is_pressing = False"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 304,
+   "execution_count": 179,
    "metadata": {},
    "outputs": [],
    "source": [
+    "# 두 벡터 사이의 각도를 구한다.\n",
+    "# param : A, B - 벡터를 표현한 ndarray이다.\n",
+    "# return : angle - 벡터 A와 B 사이의 각도이다.\n",
+    "def angle_between(A, B):\n",
+    "\n",
+    "    x1 = A[0]\n",
+    "    y1 = A[1]\n",
+    "    x2 = B[0]\n",
+    "    y2 = B[1]\n",
+    "\n",
+    "    dot = x1*x2 + y1*y2      \n",
+    "    det = x1*y2 - y1*x2     \n",
+    "    angle = np.arctan2(det, dot) * 180/np.pi  \n",
+    "\n",
+    "    return angle"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 180,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 다음 순서를 갖도록 꼭짓점을 정렬한다.\n",
+    "# top left, top right, bottom right, bottom left\n",
+    "# param : points - 정렬되기 전의 꼭짓점의 ndarray이다.\n",
+    "# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.\n",
     "def sort_points(points):\n",
     "\n",
     "    points = points.astype(np.float32)\n",
     "\n",
     "    new_points = np.zeros((4, 2), dtype = \"float32\")\n",
     " \n",
-    "\n",
+    "    # top left를 구한다.\n",
     "    s = points.sum(axis = 1)\n",
     "    min_index = np.argmin(s)\n",
     "    new_points[0] = points[min_index]\n",
     "    points = np.delete(points, min_index, axis = 0)\n",
-    "\n",
+    "    # bottom right를 구한다.\n",
     "    s = points.sum(axis = 1)\n",
     "    max_index = np.argmax(s)\n",
     "    new_points[2] = points[max_index]\n",
     "    points = np.delete(points, max_index, axis = 0)\n",
-    "\n",
+    "    # top right, bottom left를 구한다.\n",
     "    v0 = points[0] - new_points[0]\n",
     "    v1 = points[1] - new_points[0]\n",
     "\n",
     "    angle = angle_between(v0, v1)\n",
-    "\n",
+    "    # angle_between() : 벡터 사이의 각도를 구한다.\n",
     "    if angle < 0:\n",
     "        new_points[1] = points[1]\n",
     "        new_points[3] = points[0]\n",
@@ -116,76 +145,75 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 305,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "def angle_between(A, B):\n",
-    "\n",
-    "    x1 = A[0]\n",
-    "    y1 = A[1]\n",
-    "    x2 = B[0]\n",
-    "    y2 = B[1]\n",
-    "\n",
-    "    dot = x1*x2 + y1*y2      \n",
-    "    det = x1*y2 - y1*x2     \n",
-    "    angle = np.arctan2(det, dot) * 180/np.pi  \n",
-    "\n",
-    "    return angle"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 306,
+   "execution_count": 181,
    "metadata": {},
    "outputs": [],
    "source": [
-    "# 마우스를 이용하여 책의 꼭지점을 조정한다.\n",
-    "def mouse_callback(event,x,y,flags,param):\n",
-    "    \n",
-    "    global mouse_is_pressing, points\n",
-    "\n",
-    "    if step != 1:\n",
-    "        return\n",
-    "\n",
-    "    if event == cv2.EVENT_MOUSEMOVE: \n",
-    "        if mouse_is_pressing == True:  ## 마우스가 움직이고, 눌린상태일때\n",
-    "\n",
-    "            for i,point in enumerate(points):\n",
-    "                if distance((x,y), point) < 15:  ##마우스의  좌표와, 포인트(꼭지점) 의 거리가 가깝다면\n",
-    "                    points[i][0] = x             ##꼭지점을 이동한다\n",
-    "                    points[i][1] = y\n",
-    "                    break    \n",
-    "          \n",
-    "    elif event == cv2.EVENT_LBUTTONDOWN:         ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면\n",
-    "                                                  ##press 를 Ture로 바꾼다.\n",
-    "        for point in points:\n",
-    "            if distance((x,y), point) < 10:\n",
-    "                mouse_is_pressing = True\n",
-    "                break\n",
-    "\n",
-    "    elif event == cv2.EVENT_LBUTTONUP:           ## 마우스가 안눌려있으면, press 를 false로 바꿈\n",
-    "\n",
-    "        mouse_is_pressing = False"
+    "# 이미지(문서 영역)를 정면 방향으로 변환한다.\n",
+    "# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.\n",
+    "# return : img_warped - 정면 방향으로 변환된 이미지이다.\n",
+    "def transform(img_input, points):\n",
+    "    # 다음 순서롤 갖도록 꼭지점을 정렬한다.\n",
+    "    # top left, top right, bottom right, bottom left\n",
+    "    points = sort_points(points)\n",
+    "    topLeft, topRight, bottomRight, bottomLeft = points\n",
+    "    print(topLeft, topRight, bottomRight, bottomLeft)\n",
+    "    print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],\n",
+    "     bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])\n",
+    " \n",
+    "    # 변환 후 책의 너비와 높이를 결정한다.\n",
+    "    topWidth = distance(bottomLeft, bottomRight)\n",
+    "    bottomWidth = distance(topLeft, topRight)\n",
+    "    maxWidth = max(int(topWidth), int(bottomWidth))\n",
+    " \n",
+    "    leftHeight = distance(topLeft, bottomLeft)\n",
+    "    rightHeight = distance(topRight, bottomRight)\n",
+    "    maxHeight = max(int(leftHeight), int(rightHeight))\n",
+    " \n",
+    "    # 정면에서 바라본 책의 좌표를 결정한다.\n",
+    "    dst = np.array([[0, 0],[maxWidth - 1, 0],\n",
+    "        [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = \"float32\")\n",
+    " \n",
+    "    H = cv2.getPerspectiveTransform(points, dst)\n",
+    "    img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))\n",
+    " \n",
+    "    return img_warped\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 307,
+   "execution_count": 182,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def distance(point1, point2):\n",
+    "# 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
+    "# param : contours - 컨투어들의 리스트이다.\n",
+    "# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.\n",
+    "def findMaxArea(contours):  \n",
+    "    max_area = -1\n",
+    "    max_index = -1\n",
     "    \n",
-    "    x1,y1 = point1\n",
-    "    x2,y2 = point2\n",
-    " \n",
-    "    return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))"
+    "    # 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
+    "    for i,contour in enumerate(contours):\n",
+    "        # cv2.contourArea : 컨투어의 넓이를 얻는다.\n",
+    "        area = cv2.contourArea(contour)\n",
+    "        # cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.\n",
+    "        x,y,w,h = cv2.boundingRect(contour)\n",
+    "        if (w*h)*0.4 > area:\n",
+    "            continue\n",
+    "        if w > h:\n",
+    "            continue\n",
+    "        if area > max_area:\n",
+    "            max_area = area\n",
+    "            max_index = i\n",
+    "    if max_area < 10000:\n",
+    "        max_index = -1\n",
+    "    return max_index"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 308,
+   "execution_count": 183,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -204,13 +232,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 309,
+   "execution_count": 184,
    "metadata": {},
    "outputs": [],
    "source": [
     "def scanning(image):\n",
     "    #grabcut , 배경 제거\n",
     "    points = []\n",
+    "\n",
     "    height,width =image.shape[:2]\n",
     "    image_mask = np.zeros(image.shape[:2], np.uint8)\n",
     "\n",
@@ -240,6 +269,9 @@
     "    image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1)\n",
     "    #cv2.imwrite('./modified/' +i, image_canny)\n",
     "    #print(i + \"save image_canny!\")\n",
+    "    global contours\n",
+    "    global max_index\n",
+    "    global max_contour\n",
     "\n",
     "    #cv2.imshow('morphology', image_canny)\n",
     "    #cv2.waitKey(0)\n",
@@ -253,16 +285,15 @@
     "    image_fixed = image.copy()\n",
     "    if max_index < 0:\n",
     "        print(\"max_index < 0, return points \")\n",
-    "        #print(points)\n",
+    "        points = np.array([[10,10], [290, 10], [290, 390], [290, 390]])\n",
     "        return points\n",
     "\n",
+    "    \n",
     "    max_contour = contours[max_index]\n",
     "\n",
     "\n",
     "    #image_contour = image.copy()\n",
     "    #cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)\n",
-    "    #cv2.imwrite('./modified/' +i, image_contour)\n",
-    "    #print(i + \"save image_contour!\")\n",
     "    #cv2.imshow('Contour', image_contour)\n",
     "    #cv2.waitKey(0)\n",
     "\n",
@@ -308,7 +339,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 310,
+   "execution_count": 185,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -333,12 +364,12 @@
     "        \n",
     "        cv2.imshow('input', image_result)\n",
     "        cv2.imshow('result', image_final)\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
+    "        cv2.imwrite(modified_path +i, image_final)\n",
     "        print(i + \" i got 4 edges!!\")\n",
     "        \n",
     "    else:\n",
     "        cv2.imshow('input', image)\n",
-    "        cv2.imwrite('./modified/' +i, image)\n",
+    "        cv2.imwrite(modified_path +i, image)\n",
     "        print(i + \" i don't got 4 edges!\")\n",
     "    cv2.waitKey(0)\n",
     "    cv2.destroyAllWindows()\n",
@@ -347,7 +378,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 311,
+   "execution_count": 186,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -355,11 +386,11 @@
     "    if sizes == 4:\n",
     "        image_final = transform(image, points)\n",
     "        cv2.imshow('result', image_final)\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
+    "        cv2.imwrite(modified_path +i, image_final)\n",
     "        print(i + \" i got 4 edges!!/no button\")\n",
     "    else:\n",
     "        cv2.imshow('input', image)\n",
-    "        cv2.imwrite('./modified/' +i, image)\n",
+    "        cv2.imwrite(modified_path +i, image)\n",
     "        print(i + \" i don't got 4 edges!/no button\")\n",
     "    cv2.waitKey(0)\n",
     "    cv2.destroyAllWindows()\n",
@@ -368,57 +399,98 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 312,
+   "execution_count": 195,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "max_index < 0, return points \n",
-      "size 0\n",
-      "document.jpg i don't got 4 edges!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[20. 39.] [213.  14.] [277. 322.] [ 76. 303.]\n",
+      "59.0 227.0 599.0 379.0\n",
+      "document.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[36. 43.] [265.  40.] [275. 377.] [ 21. 375.]\n",
+      "79.0 305.0 652.0 396.0\n",
+      "example.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[54. 42.] [256.  57.] [266. 347.] [ 44. 349.]\n",
+      "96.0 313.0 613.0 393.0\n",
+      "example2.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[53. 24.] [267.  58.] [267. 379.] [ 10. 318.]\n",
+      "77.0 325.0 646.0 328.0\n",
+      "example2.png i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[43. 30.] [263.  27.] [272. 360.] [ 52. 365.]\n",
+      "73.0 290.0 632.0 417.0\n",
+      "example3.jpg.png i got 4 edges!!\n",
       "len of max_contour 5\n",
       "size 4\n",
-      "[19. 70.] [121.  24.] [199. 157.] [106. 213.]\n",
-      "89.0 145.0 356.0 319.0\n",
+      "[75.  8.] [237.  11.] [229. 381.] [ 68. 377.]\n",
+      "83.0 248.0 610.0 445.0\n",
+      "receipt.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[ 20. 100.] [152.  27.] [279. 290.] [131. 371.]\n",
+      "120.0 179.0 569.0 502.0\n",
       "receipt2.jpg i got 4 edges!!\n",
       "len of max_contour 8\n",
       "size 4\n",
-      "[18. 45.] [138.  32.] [158. 211.] [ 39. 225.]\n",
-      "63.0 170.0 369.0 264.0\n",
+      "[25. 73.] [208.  51.] [242. 333.] [ 60. 355.]\n",
+      "98.0 259.0 575.0 415.0\n",
       "tilted receipt.jpg i got 4 edges!!\n"
      ]
     }
    ],
    "source": [
     "mouse_is_pressing = False\n",
-    "for i in os.listdir('./images/'): \n",
-    "    path = './images/'+i \n",
-    "    count = len(os.listdir('./images/'))\n",
-    "    \n",
+    "image_path = './images/'\n",
+    "if not os.path.isdir(image_path):                                                           \n",
+    "    os.mkdir(image_path)\n",
+    "\n",
+    "for i in os.listdir(image_path): \n",
+    "    path = image_path + i \n",
+    "    count = len(os.listdir(image_path))\n",
     "    \n",
+    "    if count == 0:\n",
+    "        print(\"there are no images\")\n",
     "    image = cv2.imread(path, cv2.IMREAD_COLOR)\n",
-    "    #image=cv2.resize(image,(500,500))\n",
+    "    image=cv2.resize(image,(300,400))\n",
     "    points = scanning(image)\n",
     "    sizes = len(points)\n",
     "    print(\"size\",sizes)\n",
     "    \n",
     "    win = tk.Tk()\n",
     "    win.title(\"Ask\")\n",
-    "    win.geometry(\"500x500+50+50\")\n",
+    "    win.geometry(\"600x600+50+50\")\n",
     "    win.resizable(False, False)\n",
     "\n",
     "    lbl = tk.Label(win, text=\"마우스 입력 O/X?\")\n",
     "    #lbl.grid(row=1, column=1)\n",
     "    lbl.pack()\n",
+    "    image_contour = image.copy()\n",
+    "    cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)\n",
+    "    \n",
+    "    contour_path = './contour/'\n",
+    "    if not os.path.isdir(contour_path):                                                           \n",
+    "        os.mkdir(contour_path)\n",
+    "    \n",
+    "    cv2.imwrite(contour_path +i, image_contour)\n",
     "\n",
-    "    cv2.imwrite('./contours/' +i, image) \n",
-    "\n",
-    "    imgtk = ImageTk.PhotoImage(file = './contours/' +i, master=win)\n",
+    "    imgtk = ImageTk.PhotoImage(file = contour_path +i, master=win)\n",
     "    label = tk.Label(win, image=imgtk)\n",
     "    label.pack()\n",
     "\n",
+    "    modified_path = './modified/'\n",
+    "    if not os.path.isdir(modified_path):                                                           \n",
+    "        os.mkdir(modified_path)\n",
     "    b1 = tk.Button(win, text='마우스 입력O', command = b1event)\n",
     "    b2 = tk.Button(win, text='마우스 입력X', command = b2event)\n",
     "    #b1.grid(row=3, column=1)\n",
@@ -426,75 +498,25 @@
     "    b1.pack()\n",
     "    b2.pack()\n",
     "\n",
-    "    win.mainloop()\n",
-    "    \n",
-    "    \"\"\"\n",
-    "    size = len(points)\n",
-    "    print(\"size\" ,size)\n",
-    "    if size == 4:\n",
-    "\n",
-    "        cv2.namedWindow('input')\n",
-    "        cv2.setMouseCallback(\"input\", mouse_callback, 0);  \n",
-    "\n",
-    "\n",
-    "        step = 1\n",
-    "\n",
-    "      # 마우스를 이용하여 꼭지점을 조정한다.\n",
-    "        while True:\n",
-    "\n",
-    "            image_result = image.copy()\n",
-    "            for point in points:\n",
-    "                cv2.circle(image_result, tuple(point), 10, (255,0,0), 3 )    \n",
-    "            cv2.imshow('input', image_result)\n",
-    "\n",
-    "            key = cv2.waitKey(1)\n",
-    "            if key == 32:  # 스페이스바를 누르면 선택, \n",
-    "                break\n",
-    "\n",
-    "      # 꼭지점을 이용하여 정면에서 본 책으로 변환한다.\n",
-    "        image_final = transform(image, points )\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
-    "        print(i + \"save image_final!\")\n",
-    "\n",
-    "        cv2.imshow('input', image_result)\n",
-    "        cv2.imshow('result', image_final )\n",
-    "    else:\n",
-    "        cv2.imshow('input', image)\n",
-    "        \n",
-    "    cv2.waitKey(0)\n",
-    "    cv2.destroyAllWindows()\n",
-    "    win.destroy()\n",
-    "    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
-    "\n",
-    "    sharpen = cv2.GaussianBlur(gray, (0,0), 3)\n",
-    "    sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0)\n",
-    "    thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15)\n",
-    "    cv2.imwrite('./modified/' +i, thresh)\n",
-    "    print(i + \" save thresh!\")\n",
-    "    cv2.imshow('final_image', thresh)\n",
-    "    cv2.waitKey(0)\n",
-    "    #cv2.imwrite('./modified/' +i, modified) \n",
-    "\n",
-    "    #cv2.imshow( \"image\", image)\n",
-    "    #cv2.waitKey(0)\n",
-    "\n",
-    "\"\"\""
+    "    win.mainloop()"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 286,
+   "execution_count": 150,
    "metadata": {},
    "outputs": [
     {
-     "ename": "ModuleNotFoundError",
-     "evalue": "No module named 'fpdf'",
+     "ename": "KeyboardInterrupt",
+     "evalue": "Interrupted by user",
      "output_type": "error",
      "traceback": [
       "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[1;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
-      "\u001b[1;32m<ipython-input-286-0a916bbbf96e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m#이미지 저장\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;31m##################아직 안합침################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mfpdf\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mFPDF\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      4\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mPIL\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mImage\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
-      "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'fpdf'"
+      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
+      "\u001b[1;32m<ipython-input-150-0a916bbbf96e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     16\u001b[0m \u001b[1;31m# ------------- ADD ALL THE IMAGES IN A LIST ------------- #\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     17\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[0mfolder\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0minput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Enter the path of the folder containing the images : '\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     19\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mdirpath\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdirnames\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfilenames\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwalk\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfolder\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     20\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mfilename\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mf\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mf\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mfilenames\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mendswith\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\".jpg\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m~\\anaconda3\\lib\\site-packages\\ipykernel\\kernelbase.py\u001b[0m in \u001b[0;36mraw_input\u001b[1;34m(self, prompt)\u001b[0m\n\u001b[0;32m    858\u001b[0m                 \u001b[1;34m\"raw_input was called, but this frontend does not support input requests.\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    859\u001b[0m             )\n\u001b[1;32m--> 860\u001b[1;33m         return self._input_request(str(prompt),\n\u001b[0m\u001b[0;32m    861\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parent_ident\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    862\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parent_header\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m~\\anaconda3\\lib\\site-packages\\ipykernel\\kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[1;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[0;32m    902\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    903\u001b[0m                 \u001b[1;31m# re-raise KeyboardInterrupt, to truncate traceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 904\u001b[1;33m                 \u001b[1;32mraise\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Interrupted by user\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    905\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    906\u001b[0m                 \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlog\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwarning\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Invalid Message:\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mexc_info\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
      ]
     }
    ],
diff --git a/Untitled.ipynb b/Untitled.ipynb
index 956cbd9b30aa743e3fea875a6b9aaffd427aae97..7fec51502cbc3200b3d0ffc6bbba1fe85e197f3d 100644
--- a/Untitled.ipynb
+++ b/Untitled.ipynb
@@ -1,32 +1,6 @@
 {
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  }
- ],
- "metadata": {
-  "kernelspec": {
-   "display_name": "Python 3",
-   "language": "python",
-   "name": "python3"
-  },
-  "language_info": {
-   "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
-   },
-   "file_extension": ".py",
-   "mimetype": "text/x-python",
-   "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.8.5"
-  }
- },
+ "cells": [],
+ "metadata": {},
  "nbformat": 4,
  "nbformat_minor": 4
 }
diff --git a/contour/document.jpg b/contour/document.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..92c30a556c2928f3e4efd2c978b81e7b55820778
Binary files /dev/null and b/contour/document.jpg differ
diff --git a/contour/example.jpg b/contour/example.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..72c150f8d6fa32a7fbb84a078d845af0741b9d86
Binary files /dev/null and b/contour/example.jpg differ
diff --git a/contour/example2.jpg b/contour/example2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9ccdd3839f35e2d836584f89f77a180489bfe387
Binary files /dev/null and b/contour/example2.jpg differ
diff --git a/contour/example2.png b/contour/example2.png
new file mode 100644
index 0000000000000000000000000000000000000000..7d4b700132fc604faf561ab86c6287b6df49aa75
Binary files /dev/null and b/contour/example2.png differ
diff --git a/contour/example3.jpg.png b/contour/example3.jpg.png
new file mode 100644
index 0000000000000000000000000000000000000000..2e015cb702f4f421399e8468c88633401a2a4b07
Binary files /dev/null and b/contour/example3.jpg.png differ
diff --git a/contour/receipt.jpg b/contour/receipt.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4646e851cf72d81472874698561f5fafeed6996b
Binary files /dev/null and b/contour/receipt.jpg differ
diff --git a/contour/receipt2.jpg b/contour/receipt2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2ea1f5f946889225eb3e207f0323d9e8b75878d6
Binary files /dev/null and b/contour/receipt2.jpg differ
diff --git a/contour/tilted receipt.jpg b/contour/tilted receipt.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..3321c2e5f09b2bc1ba4df4465f954b433449f5c3
Binary files /dev/null and b/contour/tilted receipt.jpg differ
diff --git a/contours/document.jpg b/contours/document.jpg
deleted file mode 100644
index 062132f436d67f87ce93ba88c8515743dc6f864b..0000000000000000000000000000000000000000
Binary files a/contours/document.jpg and /dev/null differ
diff --git a/contours/receipt2.jpg b/contours/receipt2.jpg
deleted file mode 100644
index fae3687cc7f737191e7f9251389ce46a77b869e4..0000000000000000000000000000000000000000
Binary files a/contours/receipt2.jpg and /dev/null differ
diff --git a/contours/tilted receipt.jpg b/contours/tilted receipt.jpg
deleted file mode 100644
index e953c15edceab39692ef99c00df46df7b656a4a3..0000000000000000000000000000000000000000
Binary files a/contours/tilted receipt.jpg and /dev/null differ
diff --git a/images/example.jpg b/images/example.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..83000e21df81b31b0d022818ae210b1d8f2b15e3
Binary files /dev/null and b/images/example.jpg differ
diff --git a/images/example2.jpg b/images/example2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..bf59c76564dc3a276adb2d4ad61c4be7b154e75d
Binary files /dev/null and b/images/example2.jpg differ
diff --git a/images/example2.png b/images/example2.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e951df84b28ca2565b268c7f977389813036035
Binary files /dev/null and b/images/example2.png differ
diff --git a/images/example3.jpg.png b/images/example3.jpg.png
new file mode 100644
index 0000000000000000000000000000000000000000..98f8959a3e5ae6493432b82e01d222669774cf58
Binary files /dev/null and b/images/example3.jpg.png differ
diff --git a/receipt.jpg b/images/receipt.jpg
similarity index 100%
rename from receipt.jpg
rename to images/receipt.jpg
diff --git a/modified/document.jpg b/modified/document.jpg
index 062132f436d67f87ce93ba88c8515743dc6f864b..51673e912e0540172bf572568c4169f2dff79228 100644
Binary files a/modified/document.jpg and b/modified/document.jpg differ
diff --git a/modified/example.jpg b/modified/example.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..8e7fff7894648a08ec4b58e73ce0000f843dd347
Binary files /dev/null and b/modified/example.jpg differ
diff --git a/modified/example2.jpg b/modified/example2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2b0e61cf4bb7543c38d467264fd23697acfbb7ec
Binary files /dev/null and b/modified/example2.jpg differ
diff --git a/modified/example2.png b/modified/example2.png
new file mode 100644
index 0000000000000000000000000000000000000000..146a0e9682d0ce726516b2f18890d374dcb60b14
Binary files /dev/null and b/modified/example2.png differ
diff --git a/modified/example3.jpg.png b/modified/example3.jpg.png
new file mode 100644
index 0000000000000000000000000000000000000000..9623dabf890feb6069b4096af081c76703b876e5
Binary files /dev/null and b/modified/example3.jpg.png differ
diff --git a/modified/receipt.jpg b/modified/receipt.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1d014e9b2178d3c0539364a4be42e445f1685a41
Binary files /dev/null and b/modified/receipt.jpg differ
diff --git a/modified/receipt2.jpg b/modified/receipt2.jpg
index 86a073a944046fbcba804e12c7125e8d05ebd02a..7c9f8bde8e4f34e43ed1efeeb668df79b2a1bf33 100644
Binary files a/modified/receipt2.jpg and b/modified/receipt2.jpg differ
diff --git a/modified/tilted receipt.jpg b/modified/tilted receipt.jpg
index 2e8bc76c5dbd58373f61493124133ffbe3240f77..1df19c2cdf48f76c7a02c46a0d9b04942c3b9c0b 100644
Binary files a/modified/tilted receipt.jpg and b/modified/tilted receipt.jpg differ
diff --git a/openCV_scanner.ipynb b/openCV_scanner.ipynb
index 313abaf19e2933cc1ffc3d469befa6dd80f71245..43b055ca01b0690b1c8052e92c204966b5c0a468 100644
--- a/openCV_scanner.ipynb
+++ b/openCV_scanner.ipynb
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 301,
+   "execution_count": 196,
    "metadata": {
     "scrolled": true
    },
@@ -20,90 +20,119 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 302,
+   "execution_count": 197,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def findMaxArea(contours):  \n",
-    "    max_area = -1\n",
-    "    max_index = -1\n",
-    "    for i,contour in enumerate(contours):\n",
-    "        area = cv2.contourArea(contour)\n",
-    "        x,y,w,h = cv2.boundingRect(contour)\n",
-    "        if (w*h)*0.4 > area:\n",
-    "            continue\n",
-    "        if w > h:\n",
-    "            continue\n",
-    "        if area > max_area:\n",
-    "            max_area = area\n",
-    "            max_index = i\n",
-    "    if max_area < 10000:\n",
-    "        max_index = -1\n",
-    "    return max_index"
+    "# 두 점 사이의 거리를 구한다.\n",
+    "# param : point1, point2 - 거리를 구할 두 점이다.\n",
+    "# return : point1, point2 사이의 거리이다.\n",
+    "def distance(point1, point2):\n",
+    "    \n",
+    "    x1,y1 = point1\n",
+    "    x2,y2 = point2\n",
+    " \n",
+    "    return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 303,
+   "execution_count": 203,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def transform(img_input, points):\n",
-    "    # 다음 순서롤 갖도록 꼭지점을 정렬한다.\n",
-    "    # top left, top right, bottom right, bottom left\n",
-    "    points = sort_points(points)\n",
-    "    topLeft, topRight, bottomRight, bottomLeft = points\n",
-    "    print(topLeft, topRight, bottomRight, bottomLeft)\n",
-    "    print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],\n",
-    "     bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])\n",
-    " \n",
-    "    # 변환 후 책의 너비와 높이를 결정한다.\n",
-    "    topWidth = distance(bottomLeft, bottomRight)\n",
-    "    bottomWidth = distance(topLeft, topRight)\n",
-    "    maxWidth = max(int(topWidth), int(bottomWidth))\n",
-    " \n",
-    "    leftHeight = distance(topLeft, bottomLeft)\n",
-    "    rightHeight = distance(topRight, bottomRight)\n",
-    "    maxHeight = max(int(leftHeight), int(rightHeight))\n",
-    " \n",
-    "    # 정면에서 바라본 책의 좌표를 결정한다.\n",
-    "    dst = np.array([[0, 0],[maxWidth - 1, 0],\n",
-    "        [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = \"float32\")\n",
-    " \n",
-    "    H = cv2.getPerspectiveTransform(points, dst)\n",
-    "    img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))\n",
-    " \n",
-    "    return img_warped\n"
+    "# 사용자의 마우스 입력을 통하여 이미지(문서 영역)의 꼭지점을 조정하는 마우스 콜백 함수이다.\n",
+    "# param : event - 마우스 이벤트이다, (x, y) - 윈도우 창을 기준으로 좌측 상단점 좌표이다, \n",
+    "#         flags - 마우스 이벤트가 발생할 때 키보드 또는 마우스 상태이다,\n",
+    "#         param - 전달하고 싶은 데이터로 사용하지 않아도 매개변수로 받아야 한다.\n",
+    "# return : none\n",
+    "def mouse_callback(event,x,y,flags,param):\n",
+    "    \n",
+    "    global mouse_is_pressing, points\n",
+    "    # step == 1 이면,마우스 콜백 함수가 등록된 것이다.\n",
+    "    # step != 1 이면, cv2.setMouseCallback()을 통해 마우스 콜백 함수가 등록되지 않은 것이다.\n",
+    "    if step != 1:\n",
+    "        return\n",
+    "    \n",
+    "    # CASE 1 - 마우스가 움직이고\n",
+    "    if event == cv2.EVENT_MOUSEMOVE: \n",
+    "        # 눌린상태일때\n",
+    "        if mouse_is_pressing == True:\n",
+    "            points[i][0] = x             \n",
+    "            #마우스의  좌표와, 포인트(꼭지점) 의 거리가 가깝다면 꼭지점을 이동한다\n",
+    "            for i,point in enumerate(points):\n",
+    "                if distance((x,y), point) < 15:  \n",
+    "                    points[i][0] = x             \n",
+    "                    points[i][1] = y\n",
+    "                    break    \n",
+    "    # CASE 2 - 마우스 왼쪽 버튼이 눌린 상태일 때,      \n",
+    "    elif event == cv2.EVENT_LBUTTONDOWN:\n",
+    "        # 꼭짓점과의 거리가 가깝다면 mouse_is_pressing을 True로 바꾼다.                                          ##press 를 Ture로 바꾼다.\n",
+    "        for point in points:\n",
+    "            if distance((x,y), point) < 10:\n",
+    "                mouse_is_pressing = True\n",
+    "                break\n",
+    "    # CASE3 - 마우스 왼쪽 버튼이 눌려있지 않으면, mouse_is_pressing을 False로 바꿈\n",
+    "    elif event == cv2.EVENT_LBUTTONUP:\n",
+    "\n",
+    "        mouse_is_pressing = False"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 304,
+   "execution_count": 204,
    "metadata": {},
    "outputs": [],
    "source": [
+    "# 두 벡터 사이의 각도를 구한다.\n",
+    "# param : A, B - 벡터를 표현한 ndarray이다.\n",
+    "# return : angle - 벡터 A와 B 사이의 각도이다.\n",
+    "def angle_between(A, B):\n",
+    "\n",
+    "    x1 = A[0]\n",
+    "    y1 = A[1]\n",
+    "    x2 = B[0]\n",
+    "    y2 = B[1]\n",
+    "\n",
+    "    dot = x1*x2 + y1*y2      \n",
+    "    det = x1*y2 - y1*x2     \n",
+    "    angle = np.arctan2(det, dot) * 180/np.pi  \n",
+    "\n",
+    "    return angle"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 205,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# 다음 순서를 갖도록 꼭짓점을 정렬한다.\n",
+    "# top left, top right, bottom right, bottom left\n",
+    "# param : points - 정렬되기 전의 꼭짓점의 ndarray이다.\n",
+    "# return : new_points - 정렬된 후의 꼭짓점의 ndarray이다.\n",
     "def sort_points(points):\n",
     "\n",
     "    points = points.astype(np.float32)\n",
     "\n",
     "    new_points = np.zeros((4, 2), dtype = \"float32\")\n",
     " \n",
-    "\n",
+    "    # top left를 구한다.\n",
     "    s = points.sum(axis = 1)\n",
     "    min_index = np.argmin(s)\n",
     "    new_points[0] = points[min_index]\n",
     "    points = np.delete(points, min_index, axis = 0)\n",
-    "\n",
+    "    # bottom right를 구한다.\n",
     "    s = points.sum(axis = 1)\n",
     "    max_index = np.argmax(s)\n",
     "    new_points[2] = points[max_index]\n",
     "    points = np.delete(points, max_index, axis = 0)\n",
-    "\n",
+    "    # top right, bottom left를 구한다.\n",
     "    v0 = points[0] - new_points[0]\n",
     "    v1 = points[1] - new_points[0]\n",
     "\n",
     "    angle = angle_between(v0, v1)\n",
-    "\n",
+    "    # angle_between() : 벡터 사이의 각도를 구한다.\n",
     "    if angle < 0:\n",
     "        new_points[1] = points[1]\n",
     "        new_points[3] = points[0]\n",
@@ -116,76 +145,75 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 305,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "def angle_between(A, B):\n",
-    "\n",
-    "    x1 = A[0]\n",
-    "    y1 = A[1]\n",
-    "    x2 = B[0]\n",
-    "    y2 = B[1]\n",
-    "\n",
-    "    dot = x1*x2 + y1*y2      \n",
-    "    det = x1*y2 - y1*x2     \n",
-    "    angle = np.arctan2(det, dot) * 180/np.pi  \n",
-    "\n",
-    "    return angle"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 306,
+   "execution_count": 206,
    "metadata": {},
    "outputs": [],
    "source": [
-    "# 마우스를 이용하여 책의 꼭지점을 조정한다.\n",
-    "def mouse_callback(event,x,y,flags,param):\n",
-    "    \n",
-    "    global mouse_is_pressing, points\n",
-    "\n",
-    "    if step != 1:\n",
-    "        return\n",
-    "\n",
-    "    if event == cv2.EVENT_MOUSEMOVE: \n",
-    "        if mouse_is_pressing == True:  ## 마우스가 움직이고, 눌린상태일때\n",
-    "\n",
-    "            for i,point in enumerate(points):\n",
-    "                if distance((x,y), point) < 15:  ##마우스의  좌표와, 포인트(꼭지점) 의 거리가 가깝다면\n",
-    "                    points[i][0] = x             ##꼭지점을 이동한다\n",
-    "                    points[i][1] = y\n",
-    "                    break    \n",
-    "          \n",
-    "    elif event == cv2.EVENT_LBUTTONDOWN:         ##마우스버튼이 눌린상태에서, 꼭짓점과의 거리가 가깝다면\n",
-    "                                                  ##press 를 Ture로 바꾼다.\n",
-    "        for point in points:\n",
-    "            if distance((x,y), point) < 10:\n",
-    "                mouse_is_pressing = True\n",
-    "                break\n",
-    "\n",
-    "    elif event == cv2.EVENT_LBUTTONUP:           ## 마우스가 안눌려있으면, press 를 false로 바꿈\n",
-    "\n",
-    "        mouse_is_pressing = False"
+    "# 이미지(문서 영역)를 정면 방향으로 변환한다.\n",
+    "# param : img_input - 정면 방향으로 변환할 이미지이다, points - img_input의 꼭짓점이다.\n",
+    "# return : img_warped - 정면 방향으로 변환된 이미지이다.\n",
+    "def transform(img_input, points):\n",
+    "    # 다음 순서롤 갖도록 꼭지점을 정렬한다.\n",
+    "    # top left, top right, bottom right, bottom left\n",
+    "    points = sort_points(points)\n",
+    "    topLeft, topRight, bottomRight, bottomLeft = points\n",
+    "    print(topLeft, topRight, bottomRight, bottomLeft)\n",
+    "    print(topLeft[0] + topLeft[1], topRight[0]+topRight[1],\n",
+    "     bottomRight[0]+bottomRight[1], bottomLeft[0]+bottomLeft[1])\n",
+    " \n",
+    "    # 변환 후 책의 너비와 높이를 결정한다.\n",
+    "    topWidth = distance(bottomLeft, bottomRight)\n",
+    "    bottomWidth = distance(topLeft, topRight)\n",
+    "    maxWidth = max(int(topWidth), int(bottomWidth))\n",
+    " \n",
+    "    leftHeight = distance(topLeft, bottomLeft)\n",
+    "    rightHeight = distance(topRight, bottomRight)\n",
+    "    maxHeight = max(int(leftHeight), int(rightHeight))\n",
+    " \n",
+    "    # 정면에서 바라본 책의 좌표를 결정한다.\n",
+    "    dst = np.array([[0, 0],[maxWidth - 1, 0],\n",
+    "        [maxWidth - 1, maxHeight - 1],[0, maxHeight - 1]], dtype = \"float32\")\n",
+    " \n",
+    "    H = cv2.getPerspectiveTransform(points, dst)\n",
+    "    img_warped = cv2.warpPerspective(img_input, H, (maxWidth, maxHeight))\n",
+    " \n",
+    "    return img_warped\n"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 307,
+   "execution_count": 207,
    "metadata": {},
    "outputs": [],
    "source": [
-    "def distance(point1, point2):\n",
+    "# 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
+    "# param : contours - 컨투어들의 리스트이다.\n",
+    "# return : max_index - contours에서 가장 큰 영역을 갖는 컨투어의 인덱스이다.\n",
+    "def findMaxArea(contours):  \n",
+    "    max_area = -1\n",
+    "    max_index = -1\n",
     "    \n",
-    "    x1,y1 = point1\n",
-    "    x2,y2 = point2\n",
-    " \n",
-    "    return int(np.sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))"
+    "    # 가장 큰 영역을 갖는 컨투어를 찾는다.\n",
+    "    for i,contour in enumerate(contours):\n",
+    "        # cv2.contourArea : 컨투어의 넓이를 얻는다.\n",
+    "        area = cv2.contourArea(contour)\n",
+    "        # cv.boundingRect : 컨투어 라인을 둘러싸는 사각형을 그린다.\n",
+    "        x,y,w,h = cv2.boundingRect(contour)\n",
+    "        if (w*h)*0.4 > area:\n",
+    "            continue\n",
+    "        if w > h:\n",
+    "            continue\n",
+    "        if area > max_area:\n",
+    "            max_area = area\n",
+    "            max_index = i\n",
+    "    if max_area < 10000:\n",
+    "        max_index = -1\n",
+    "    return max_index"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 308,
+   "execution_count": 208,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -204,13 +232,14 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 309,
+   "execution_count": 209,
    "metadata": {},
    "outputs": [],
    "source": [
     "def scanning(image):\n",
     "    #grabcut , 배경 제거\n",
     "    points = []\n",
+    "\n",
     "    height,width =image.shape[:2]\n",
     "    image_mask = np.zeros(image.shape[:2], np.uint8)\n",
     "\n",
@@ -240,6 +269,9 @@
     "    image_canny = cv2.morphologyEx(image_canny, cv2.MORPH_CLOSE, kernel, 1)\n",
     "    #cv2.imwrite('./modified/' +i, image_canny)\n",
     "    #print(i + \"save image_canny!\")\n",
+    "    global contours\n",
+    "    global max_index\n",
+    "    global max_contour\n",
     "\n",
     "    #cv2.imshow('morphology', image_canny)\n",
     "    #cv2.waitKey(0)\n",
@@ -253,16 +285,15 @@
     "    image_fixed = image.copy()\n",
     "    if max_index < 0:\n",
     "        print(\"max_index < 0, return points \")\n",
-    "        #print(points)\n",
+    "        points = np.array([[10,10], [290, 10], [290, 390], [290, 390]])\n",
     "        return points\n",
     "\n",
+    "    \n",
     "    max_contour = contours[max_index]\n",
     "\n",
     "\n",
     "    #image_contour = image.copy()\n",
     "    #cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)\n",
-    "    #cv2.imwrite('./modified/' +i, image_contour)\n",
-    "    #print(i + \"save image_contour!\")\n",
     "    #cv2.imshow('Contour', image_contour)\n",
     "    #cv2.waitKey(0)\n",
     "\n",
@@ -308,7 +339,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 310,
+   "execution_count": 210,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -333,12 +364,12 @@
     "        \n",
     "        cv2.imshow('input', image_result)\n",
     "        cv2.imshow('result', image_final)\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
+    "        cv2.imwrite(modified_path +i, image_final)\n",
     "        print(i + \" i got 4 edges!!\")\n",
     "        \n",
     "    else:\n",
     "        cv2.imshow('input', image)\n",
-    "        cv2.imwrite('./modified/' +i, image)\n",
+    "        cv2.imwrite(modified_path +i, image)\n",
     "        print(i + \" i don't got 4 edges!\")\n",
     "    cv2.waitKey(0)\n",
     "    cv2.destroyAllWindows()\n",
@@ -347,7 +378,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 311,
+   "execution_count": 211,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -355,11 +386,11 @@
     "    if sizes == 4:\n",
     "        image_final = transform(image, points)\n",
     "        cv2.imshow('result', image_final)\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
+    "        cv2.imwrite(modified_path +i, image_final)\n",
     "        print(i + \" i got 4 edges!!/no button\")\n",
     "    else:\n",
     "        cv2.imshow('input', image)\n",
-    "        cv2.imwrite('./modified/' +i, image)\n",
+    "        cv2.imwrite(modified_path +i, image)\n",
     "        print(i + \" i don't got 4 edges!/no button\")\n",
     "    cv2.waitKey(0)\n",
     "    cv2.destroyAllWindows()\n",
@@ -368,57 +399,98 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 312,
+   "execution_count": null,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "max_index < 0, return points \n",
-      "size 0\n",
-      "document.jpg i don't got 4 edges!\n",
-      "len of max_contour 5\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[20. 39.] [213.  14.] [277. 322.] [ 76. 303.]\n",
+      "59.0 227.0 599.0 379.0\n",
+      "document.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[36. 43.] [265.  40.] [274. 369.] [ 21. 375.]\n",
+      "79.0 305.0 643.0 396.0\n",
+      "example.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[54. 42.] [256.  57.] [266. 347.] [ 44. 349.]\n",
+      "96.0 313.0 613.0 393.0\n",
+      "example2.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[53. 24.] [267.  58.] [267. 379.] [ 10. 318.]\n",
+      "77.0 325.0 646.0 328.0\n",
+      "example2.png i got 4 edges!!\n",
+      "len of max_contour 4\n",
+      "size 4\n",
+      "[43. 30.] [263.  27.] [272. 360.] [ 52. 365.]\n",
+      "73.0 290.0 632.0 417.0\n",
+      "example3.jpg.png i got 4 edges!!\n",
+      "len of max_contour 7\n",
+      "size 4\n",
+      "[74.  9.] [273.   8.] [275. 376.] [ 77. 378.]\n",
+      "83.0 281.0 651.0 455.0\n",
+      "receipt.jpg i got 4 edges!!\n",
+      "len of max_contour 4\n",
       "size 4\n",
-      "[19. 70.] [121.  24.] [199. 157.] [106. 213.]\n",
-      "89.0 145.0 356.0 319.0\n",
+      "[ 20. 100.] [152.  27.] [279. 290.] [131. 371.]\n",
+      "120.0 179.0 569.0 502.0\n",
       "receipt2.jpg i got 4 edges!!\n",
       "len of max_contour 8\n",
       "size 4\n",
-      "[18. 45.] [138.  32.] [158. 211.] [ 39. 225.]\n",
-      "63.0 170.0 369.0 264.0\n",
+      "[25. 74.] [208.  51.] [243. 334.] [ 60. 357.]\n",
+      "99.0 259.0 577.0 417.0\n",
       "tilted receipt.jpg i got 4 edges!!\n"
      ]
     }
    ],
    "source": [
     "mouse_is_pressing = False\n",
-    "for i in os.listdir('./images/'): \n",
-    "    path = './images/'+i \n",
-    "    count = len(os.listdir('./images/'))\n",
-    "    \n",
+    "image_path = './images/'\n",
+    "if not os.path.isdir(image_path):                                                           \n",
+    "    os.mkdir(image_path)\n",
+    "\n",
+    "for i in os.listdir(image_path): \n",
+    "    path = image_path + i \n",
+    "    count = len(os.listdir(image_path))\n",
     "    \n",
+    "    if count == 0:\n",
+    "        print(\"there are no images\")\n",
     "    image = cv2.imread(path, cv2.IMREAD_COLOR)\n",
-    "    #image=cv2.resize(image,(500,500))\n",
+    "    image=cv2.resize(image,(300,400))\n",
     "    points = scanning(image)\n",
     "    sizes = len(points)\n",
     "    print(\"size\",sizes)\n",
     "    \n",
     "    win = tk.Tk()\n",
     "    win.title(\"Ask\")\n",
-    "    win.geometry(\"500x500+50+50\")\n",
+    "    win.geometry(\"600x600+50+50\")\n",
     "    win.resizable(False, False)\n",
     "\n",
     "    lbl = tk.Label(win, text=\"마우스 입력 O/X?\")\n",
     "    #lbl.grid(row=1, column=1)\n",
     "    lbl.pack()\n",
+    "    image_contour = image.copy()\n",
+    "    cv2.drawContours(image_contour, [max_contour], 0, (0, 0, 255), 3)\n",
+    "    \n",
+    "    contour_path = './contour/'\n",
+    "    if not os.path.isdir(contour_path):                                                           \n",
+    "        os.mkdir(contour_path)\n",
+    "    \n",
+    "    cv2.imwrite(contour_path +i, image_contour)\n",
     "\n",
-    "    cv2.imwrite('./contours/' +i, image) \n",
-    "\n",
-    "    imgtk = ImageTk.PhotoImage(file = './contours/' +i, master=win)\n",
+    "    imgtk = ImageTk.PhotoImage(file = contour_path +i, master=win)\n",
     "    label = tk.Label(win, image=imgtk)\n",
     "    label.pack()\n",
     "\n",
+    "    modified_path = './modified/'\n",
+    "    if not os.path.isdir(modified_path):                                                           \n",
+    "        os.mkdir(modified_path)\n",
     "    b1 = tk.Button(win, text='마우스 입력O', command = b1event)\n",
     "    b2 = tk.Button(win, text='마우스 입력X', command = b2event)\n",
     "    #b1.grid(row=3, column=1)\n",
@@ -426,75 +498,25 @@
     "    b1.pack()\n",
     "    b2.pack()\n",
     "\n",
-    "    win.mainloop()\n",
-    "    \n",
-    "    \"\"\"\n",
-    "    size = len(points)\n",
-    "    print(\"size\" ,size)\n",
-    "    if size == 4:\n",
-    "\n",
-    "        cv2.namedWindow('input')\n",
-    "        cv2.setMouseCallback(\"input\", mouse_callback, 0);  \n",
-    "\n",
-    "\n",
-    "        step = 1\n",
-    "\n",
-    "      # 마우스를 이용하여 꼭지점을 조정한다.\n",
-    "        while True:\n",
-    "\n",
-    "            image_result = image.copy()\n",
-    "            for point in points:\n",
-    "                cv2.circle(image_result, tuple(point), 10, (255,0,0), 3 )    \n",
-    "            cv2.imshow('input', image_result)\n",
-    "\n",
-    "            key = cv2.waitKey(1)\n",
-    "            if key == 32:  # 스페이스바를 누르면 선택, \n",
-    "                break\n",
-    "\n",
-    "      # 꼭지점을 이용하여 정면에서 본 책으로 변환한다.\n",
-    "        image_final = transform(image, points )\n",
-    "        cv2.imwrite('./modified/' +i, image_final)\n",
-    "        print(i + \"save image_final!\")\n",
-    "\n",
-    "        cv2.imshow('input', image_result)\n",
-    "        cv2.imshow('result', image_final )\n",
-    "    else:\n",
-    "        cv2.imshow('input', image)\n",
-    "        \n",
-    "    cv2.waitKey(0)\n",
-    "    cv2.destroyAllWindows()\n",
-    "    win.destroy()\n",
-    "    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
-    "\n",
-    "    sharpen = cv2.GaussianBlur(gray, (0,0), 3)\n",
-    "    sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0)\n",
-    "    thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15)\n",
-    "    cv2.imwrite('./modified/' +i, thresh)\n",
-    "    print(i + \" save thresh!\")\n",
-    "    cv2.imshow('final_image', thresh)\n",
-    "    cv2.waitKey(0)\n",
-    "    #cv2.imwrite('./modified/' +i, modified) \n",
-    "\n",
-    "    #cv2.imshow( \"image\", image)\n",
-    "    #cv2.waitKey(0)\n",
-    "\n",
-    "\"\"\""
+    "    win.mainloop()"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 286,
+   "execution_count": 150,
    "metadata": {},
    "outputs": [
     {
-     "ename": "ModuleNotFoundError",
-     "evalue": "No module named 'fpdf'",
+     "ename": "KeyboardInterrupt",
+     "evalue": "Interrupted by user",
      "output_type": "error",
      "traceback": [
       "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[1;31mModuleNotFoundError\u001b[0m                       Traceback (most recent call last)",
-      "\u001b[1;32m<ipython-input-286-0a916bbbf96e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m#이미지 저장\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      2\u001b[0m \u001b[1;31m##################아직 안합침################################\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[1;32mfrom\u001b[0m \u001b[0mfpdf\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mFPDF\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      4\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[0mPIL\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mImage\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;32mimport\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
-      "\u001b[1;31mModuleNotFoundError\u001b[0m: No module named 'fpdf'"
+      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
+      "\u001b[1;32m<ipython-input-150-0a916bbbf96e>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m     16\u001b[0m \u001b[1;31m# ------------- ADD ALL THE IMAGES IN A LIST ------------- #\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     17\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 18\u001b[1;33m \u001b[0mfolder\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0minput\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'Enter the path of the folder containing the images : '\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     19\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mdirpath\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdirnames\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfilenames\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mos\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwalk\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfolder\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     20\u001b[0m     \u001b[1;32mfor\u001b[0m \u001b[0mfilename\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mf\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mf\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mfilenames\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mendswith\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\".jpg\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m~\\anaconda3\\lib\\site-packages\\ipykernel\\kernelbase.py\u001b[0m in \u001b[0;36mraw_input\u001b[1;34m(self, prompt)\u001b[0m\n\u001b[0;32m    858\u001b[0m                 \u001b[1;34m\"raw_input was called, but this frontend does not support input requests.\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    859\u001b[0m             )\n\u001b[1;32m--> 860\u001b[1;33m         return self._input_request(str(prompt),\n\u001b[0m\u001b[0;32m    861\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parent_ident\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    862\u001b[0m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_parent_header\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;32m~\\anaconda3\\lib\\site-packages\\ipykernel\\kernelbase.py\u001b[0m in \u001b[0;36m_input_request\u001b[1;34m(self, prompt, ident, parent, password)\u001b[0m\n\u001b[0;32m    902\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    903\u001b[0m                 \u001b[1;31m# re-raise KeyboardInterrupt, to truncate traceback\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 904\u001b[1;33m                 \u001b[1;32mraise\u001b[0m \u001b[0mKeyboardInterrupt\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Interrupted by user\"\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    905\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    906\u001b[0m                 \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mlog\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwarning\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Invalid Message:\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mexc_info\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
+      "\u001b[1;31mKeyboardInterrupt\u001b[0m: Interrupted by user"
      ]
     }
    ],