Lugovtsov/5.2.1-frank-herz-experiment/cv-recogn.ipynb

343 lines
231 KiB
Plaintext
Raw Normal View History

2023-09-15 14:01:17 +03:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 119,
"id": "2eb81291-1ac8-43cc-a3e8-615a1a9b1ce9",
"metadata": {},
"outputs": [],
"source": [
"import cv2\n",
"from skimage import color, transform\n",
"import matplotlib.pyplot as plt \n",
"from imutils.perspective import four_point_transform\n",
"from imutils import contours\n",
"import imutils\n",
"\n",
"DIGITS_LOOKUP = {\n",
" (1, 1, 1, 0, 1, 1, 1): 0,\n",
" (0, 0, 1, 0, 0, 1, 0): 1,\n",
" (1, 0, 1, 1, 1, 1, 0): 2,\n",
" (1, 0, 1, 1, 0, 1, 1): 3,\n",
" (0, 1, 1, 1, 0, 1, 0): 4,\n",
" (1, 1, 0, 1, 0, 1, 1): 5,\n",
" (1, 1, 0, 1, 1, 1, 1): 6,\n",
" (1, 0, 1, 0, 0, 1, 0): 7,\n",
" (1, 1, 1, 1, 1, 1, 1): 8,\n",
" (1, 1, 1, 1, 0, 1, 1): 9\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 153,
"id": "8a5a5a0b-4866-4c0f-a090-3cbd633f8000",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3de47a99f0>"
]
},
"execution_count": 153,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAD3CAYAAAA3+q9WAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOz9a6wtW3YWCH5jzhkRa62993nec8+9N+/Nd9oYp99ZuHGVCxDGyIhqDJRMi26EKLpl2ioky7YoLKslG9F2Y1SA2sJIRkhGUDzUJZAaNdXtNE1jVyUgSAxt87BJZzqf95xzz3M/1iMi5hz9Y4wxY0asWPucm4bOvGJP6Zy991rxmDFjPr75jW+MQczMuCpX5apclatyVa7KVfkyKu5LXYGrclWuylW5KlflqlyVabkCKFflqlyVq3JVrspV+bIrVwDlqlyVq3JVrspVuSpfduUKoFyVq3JVrspVuSpX5cuuXAGUq3JVrspVuSpX5ap82ZUrgHJVrspVuSpX5apclS+7cgVQrspVuSpX5apclavyZVeuAMpVuSpX5apclatyVb7syhVAuSpX5apclatyVa7Kl125AihX5apclatyVa7KVfmyK19SgPKTP/mTeN/73ofFYoFv+qZvws///M9/KatzVa7KVbkqV+WqXJUvk/IlAyh/+2//bXzv934vfuiHfgi/8Au/gG/91m/Fd3zHd+Azn/nMl6pKV+WqXJWrclWuylX5Min0pUoW+M3f/M34xm/8Rvylv/SX8mdf9VVfhe/8zu/Ej/3Yj30pqnRVrspVuSpX5apclS+TEr4UN23bFh//+MfxJ//knxx9/u3f/u342Mc+tnf8brfDbrfLf6eU8PjxY9y+fRtE9B+9vlflqlyVq3JVrspV+fUXZsbZ2Rlee+01OHe5EedLAlAePnyIGCPu3r07+vzu3bu4d+/e3vE/9mM/hh/5kR/5/1f1rspVuSpX5apclavyH7F89rOfxeuvv37pMV8SgGJlyn4w8ywj8oM/+IP4vu/7vvz3s2fP8O53vxu/+Vv+O9Spgtv0cG0PJgIxgz3h/rfcxJ3/6rP4r1/7OFoOSDy+rqN5y5ZHkp+U4JDw+fYWPvbo/fi1t26h21YAE7BzqE493IZALB/lyyXAt4DrAPZAqoAUAFag6Dpg+YiBBOxuEfqFNQbAjgEC4Ibj83fF79JYxT1J/gaPvy/Pz8fPPTZPfgIAUz6ekvx0EXD6bJQASpzrQFE+Yw8kD7AnMMnfKJqeIuBbht8Cvme4lhE2CX6b4HcRrotAz6AYASKwc+BA4MojVQ7sCbGSzygxKEpbpYrk/k7u4fpUPAppmxJ8m1A/2YK2EQgOXDkk7wACqE9yzT4BkUFJr8EMzDF1Zh1NM43qaHyO/W7nEEm9PIGDQ6o94iIgLhy6lUOqCbEmxBqIDSFV8mzWL8rum7t2WcVplWg4nytGCkA8SuCjHlXTo1l2uL7Y4uZigxv1GkvfwQEILiJQzOMlMR0cS+WYsuMSHByGd5FU9lZeY3re3Of5s5lrlZ8nuL36Ta83/T7x/i4u4bBAL03+jsX1PDHczDGBEmrXo3E9jv0Wt8M5XvJnuOUv8JLf4LoDKtBo/nsR63ssXrTH/HOXx3kQPtN7/OW3/kv8f/7VV+HoUwFhi1F/IbuvddXiO9cB9WnC8lGL8HQLWu/AqwYX7z3B+mWP5Amul3mBncwJ1RkjbBP6lUO3IvmcizlO5yabQ3I9os4xVhXSsTzp53ke4uFvuQCNx27Rnntda6ap546hubGeT5g73p6Ph3uUc3Sex7lYQ3h8//weykE/85m13fQ5U/n3MGeRHTtXr7JMO3NRiBlIkwPS5F7FnAcAfdzhH/3KT+Dk5OTwhbV8SQDKSy+9BO/9Hlvy4MGDPVYFAJqmQdM0e5+H0CDECp4I5BzYORAz+usL7N7d4IOvnOPo2MHz/mP6g63uFJwACQGnF7dw6m6CFiuEmpBaD9cFBEdwtTR4Od+5DvAJICfABBVAXgcjASEBwTHSAqAjgq+QwQmT/S7nA5O+U8yYlCAdgRQgYfh7/0QMg6Usl31XAJTy2MTyTzq+nOc6AWXoZQCHNFyPFTRkkBAAXgEdAZ0+h+sBv2P4HRC2Clg2EX4b4fsEigy0CbSV0c4VIdUO7L0AIRCwk3snL0CFmNEdB6SKEDYJLjKSIziX4BsHCowUHFA7oHICKCILMGkj3KYXkOQcODiAGdRFAS/AGJz4/V4Epw1Gxc/pgsMMRMi/XQIuenBw4MoLaKk8Uu3Qrzz6pROwUglYSTUN4NdLHxiBlxmAkovek3uAz4EUGG0F3F8w3lxGuFWPetFjUXc4WexwrdniWrXFUWjRuB7BxTx+HPEekDBwEidLvEfa+8yOn7uGXb/8/dAxHgmOGB17vf/+fdxeJ7frOKQDi7ubWbmmx04ByvS7xA4dEzoAZyA8BuM+etTc4zo2eNU9xRv1I7zLP8NLvsOJ8/CgEfhIM2AlgnNdHPYBSglK5Fg57qvB+D8e/xN0i2P8k+orcPRpLyAFKBZN3utDxAC0z3XVAr5aIjzdoj9pkG40oKVDYM5dn51saBokUM2ISy/zHSDzlsd4EVdAA1Jg0yaEiwTXJRnnnsCOpL87ynMqMJm/HIa5NIP3fZCy92yHQEq58cNw3Ais2OUnGxlrR9vQjUoJUJhBUYFd2K/TFDTm60eWc9k2g5T/tueluc14BnU8bpPpPJUwP7+VdXKTa3g5bwRQZjZ5LyLP+JIAlLqu8U3f9E346Ec/it/7e39v/vyjH/0ofs/v+T0vfqGMmscP312r0d6JeM/iMQCZGD0lRJ20fNGb42QiM+bEE+MsNri3vYb1rgYRw3tGSh5uS6BIY+akYClsJ8/GnOhgAWQxJgZSoMwuMA0DavRs5d+T7xj6yHPHHHrvthXJWxKMn8EOS5MLTIGK04+096QaiMYEsQAEF3UHFAXAuJ5B3XB/W1DZE1IA0jGhPZEbuN7BtV6YqB5wHSPsGGGdEDY93C7C7fphm1sMKvZO2rf2oMjwiVGddVK3hYfrGany4IVMdql28o4YgBek5x3lSVFYDQ/fJYRnOwBpPBgdzTMo0zLZRczu7FICtQm0lfp6ZWFqAy2VRwoOqfHolx79ktCtHOICiDWBQ8HWlZPztBSTugBMAjYATo2xqpAC47wCThvGZxcJtOpRLzqsFi2OmxbH9Q7X6i2OfIujsEPjelQU9wDIiK2g4TsDOHOARZqV986fMh89y8zpmKUf8CVbvQPlMnACjMGIKwDB3HXsjLnPS6CVQDjtZMA83B3jc+4m/l31Kl6tn+GDzX28t3qIu77FETk4MhBGsyBF6iUlTlYvGx72+cDsMD5YbfHHXv2HOP/aBv+6ey9WX3Dwu3LPQqDJ9WzqSBXQnjiAKvRHHt3KoTvW+SwS2CYUBnwnk1WsHfR1DewJD33QQIr129Aymsc9mvvnoM0O7AhwDvCyMTHmkX3Rf5yMaWEnIcco45KBg809frKBKBd1zIwdu2a5qdO1R+45XNs2mXvz+exGUIFJAWBm1+1Z8DSAk/xzdM8CZE7mqAxO7IYlmChZrOexeNPvp+xJvtCEzXrB8iUz8Xzf930f/tAf+kP4yEc+gt/8m38zfuqnfgqf+cxn8Mf+2B974WtQ5BGVD0hH3N3wWL50jrvVM9QU4YlxkRo86Y/QscfKtVi5HSqK8JRkYtUeaTsgj4Qn/RHe2hwjRgdyLO+idXC60GbzhgGGJAsygIFON/SpoMC1cpwtJNKheQAxPFzvIOAowEX5UR5reg5NzikHWFn3WbNP2c7FLqI8dDQWbFF0ckJPAnSIAeoB1xOoHxgT17KwLhiYoxTEVMMOiAtCv7L2IzEN7TzCJgjLsmX4XYLrGK6VXRZ1UQZ5ZDhm1M8Aigm0i+BKJrK8i3EOyZHczwsIyvRxnmhITEC1AtvggN7JxOccEHRy7BNc2wvVmRjwbn8glhMA0eHvgYF90c+pi6BOOpanArTUQQDU0iPWYhbqG3mm2AymocyyFDvLPfre/jZQuRs6n4CWgFQ1OKuBpw2DGwEtVdNjtWh
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"image = cv2.imread(\"test-photo.jpg\")\n",
"\n",
"gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)[1600:2000, 3000:4000]\n",
"blurred = cv2.GaussianBlur(gray, (5, 5), 2)\n",
"edged = cv2.Canny(blurred, 50, 150, 255)\n",
"plt.imshow(blurred)"
]
},
{
"cell_type": "code",
"execution_count": 149,
"id": "1b20b80f-fe4f-4918-a766-beae29cd6262",
"metadata": {},
"outputs": [],
"source": [
"# find contours in the edge map, then sort them by their\n",
"# size in descending order\n",
"cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,\n",
" cv2.CHAIN_APPROX_SIMPLE)\n",
"cnts = imutils.grab_contours(cnts)\n",
"cnts = sorted(cnts, key=cv2.contourArea, reverse=True)\n",
"displayCnt = []\n",
"# loop over the contours\n",
"for c in cnts:\n",
" # approximate the contour\n",
" peri = cv2.arcLength(c, True)\n",
" approx = cv2.approxPolyDP(c, 0.02 * peri, True)\n",
" \n",
" # if the contour has four vertices, then we have found\n",
" # the display\n",
" if (len(approx) == 4) and (peri > 800):\n",
" displayCnt.append(approx)"
]
},
{
"cell_type": "code",
"execution_count": 150,
"id": "1332a470-1561-47fd-a809-4858d381c49d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[array([[[276, 83]],\n",
" \n",
" [[709, 191]],\n",
" \n",
" [[736, 132]],\n",
" \n",
" [[304, 25]]], dtype=int32),\n",
" array([[[811, 153]],\n",
" \n",
" [[781, 260]],\n",
" \n",
" [[813, 154]],\n",
" \n",
" [[999, 361]]], dtype=int32)]"
]
},
"execution_count": 150,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"displayCnt"
]
},
{
"cell_type": "code",
"execution_count": 151,
"id": "4db67c7a-520e-4733-b2b1-338c11149b6b",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"n = len(displayCnt)\n",
"fig, ax = plt.subplots(n, 1)\n",
"for i in range(n):\n",
" warped = four_point_transform(gray, displayCnt[i].reshape(4, 2))\n",
" ax[i].imshow(warped)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "f85617df-aa30-4245-a6d5-f9a92ef15f7a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.image.AxesImage at 0x7f3df71c9de0>"
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# threshold the warped image, then apply a series of morphological\n",
"# operations to cleanup the thresholded image\n",
"thresh = cv2.threshold(warped, 0, 255,\n",
" cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]\n",
"kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2, 8))\n",
"thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)\n",
"plt.imshow(thresh)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "97e389e3-1344-414b-b762-1ec261aa6032",
"metadata": {},
"outputs": [],
"source": [
"# find contours in the thresholded image, then initialize the\n",
"# digit contours lists\n",
"can = cv2.Canny(thresh, 50, 200, 255)\n",
"cnts = cv2.findContours(can.copy(), cv2.RETR_EXTERNAL,\n",
" cv2.CHAIN_APPROX_SIMPLE)\n",
"cnts = imutils.grab_contours(cnts)\n",
"digitCnts = []\n",
"\n",
"# loop over the digit area candidates\n",
"for c in cnts:\n",
" # compute the bounding box of the contour\n",
" (x, y, w, h) = cv2.boundingRect(c)\n",
" # print((x, y, w, h))\n",
" \n",
" # if the contour is sufficiently large, it must be a digit\n",
" if w >= 30 and (h >= 30 and h <= 60):\n",
" digitCnts.append(c)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "dcc6b926-37ae-4a95-97b9-5d560cedada9",
"metadata": {},
"outputs": [],
"source": [
"# sort the contours from left-to-right, then initialize the\n",
"# actual digits themselves\n",
"digitCnts = contours.sort_contours(digitCnts,\n",
" method=\"left-to-right\")[0]\n",
"digits = []"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "523725fa-be66-4734-983d-fb60e1c1a488",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"ename": "KeyError",
"evalue": "(0, 1, 0, 1, 0, 1, 0)",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[18], line 42\u001b[0m\n\u001b[1;32m 39\u001b[0m on[i]\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;66;03m# lookup the digit and draw it on the image\u001b[39;00m\n\u001b[0;32m---> 42\u001b[0m digit \u001b[38;5;241m=\u001b[39m \u001b[43mDIGITS_LOOKUP\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;28;43mtuple\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mon\u001b[49m\u001b[43m)\u001b[49m\u001b[43m]\u001b[49m\n\u001b[1;32m 43\u001b[0m digits\u001b[38;5;241m.\u001b[39mappend(digit)\n\u001b[1;32m 44\u001b[0m cv2\u001b[38;5;241m.\u001b[39mrectangle(output, (x, y), (x \u001b[38;5;241m+\u001b[39m w, y \u001b[38;5;241m+\u001b[39m h), (\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m255\u001b[39m, \u001b[38;5;241m0\u001b[39m), \u001b[38;5;241m1\u001b[39m)\n",
"\u001b[0;31mKeyError\u001b[0m: (0, 1, 0, 1, 0, 1, 0)"
]
}
],
"source": [
"# loop over each of the digits\n",
"for c in digitCnts:\n",
" # extract the digit ROI\n",
" (x, y, w, h) = cv2.boundingRect(c)\n",
" roi = thresh[y:y + h, x:x + w]\n",
" plt.imshow(roi)\n",
" plt.show()\n",
" \n",
" # compute the width and height of each of the 7 segments\n",
" # we are going to examine\n",
" (roiH, roiW) = roi.shape\n",
" (dW, dH) = (int(roiW * 0.25), int(roiH * 0.15))\n",
" dHC = int(roiH * 0.05)\n",
" \n",
" # define the set of 7 segments\n",
" segments = [\n",
" ((0, 0), (w, dH)), # top\n",
" ((0, 0), (dW, h // 2)), # top-left\n",
" ((w - dW, 0), (w, h // 2)), # top-right\n",
" ((0, (h // 2) - dHC) , (w, (h // 2) + dHC)), # center\n",
" ((0, h // 2), (dW, h)), # bottom-left\n",
" ((w - dW, h // 2), (w, h)), # bottom-right\n",
" ((0, h - dH), (w, h)) # bottom\n",
" ]\n",
" on = [0] * len(segments)\n",
" \n",
" # loop over the segments\n",
" for (i, ((xA, yA), (xB, yB))) in enumerate(segments):\n",
" # extract the segment ROI, count the total number of\n",
" # thresholded pixels in the segment, and then compute\n",
" # the area of the segment\n",
" segROI = roi[yA:yB, xA:xB]\n",
" total = cv2.countNonZero(segROI)\n",
" area = (xB - xA) * (yB - yA)\n",
" \n",
" # if the total number of non-zero pixels is greater than\n",
" # 50% of the area, mark the segment as \"on\"\n",
" if total / float(area) > 0.5:\n",
" on[i]= 1\n",
"\n",
" # lookup the digit and draw it on the image\n",
" digit = DIGITS_LOOKUP[tuple(on)]\n",
" digits.append(digit)\n",
" cv2.rectangle(output, (x, y), (x + w, y + h), (0, 255, 0), 1)\n",
" cv2.putText(output, str(digit), (x - 10, y - 10),\n",
" cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255, 0), 2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4d1b2e22-d0f8-4276-b051-79b3a4279c9e",
"metadata": {},
"outputs": [],
"source": [
"# display the digits\n",
"print(u\"{}{}.{} \\u00b0C\".format(*digits))\n",
"cv2.imshow(\"Input\", image)\n",
"cv2.imshow(\"Output\", output)\n",
"cv2.waitKey(0)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.10.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}