{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "metadata": {} }, "outputs": [], "source": [ "import cv2\n", "import numpy as np\n", "import os\n", "\n", "INTERVV = [0.09, 0.29, 0.5, 0.7, 0.91]\n", "INTERVH = [0.33, 0.6]\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "metadata": {} }, "outputs": [], "source": [ "def draw_interactive_polygon(image_path):\n", " # Initialize variables\n", " points = []\n", " moving = False\n", " current_point_index = -1\n", "\n", " original_image = cv2.flip(cv2.imread(image_path), 1)\n", " image = original_image.copy()\n", " window_name = \"Polygon Drawer\"\n", "\n", " def interpolate(p1, p2, t):\n", " \"\"\"Linearly interpolate between points p1 and p2 with parameter t\"\"\"\n", " return [int((1 - t) * p1[0] + t * p2[0]), int((1 - t) * p1[1] + t * p2[1])]\n", "\n", " def draw_additional_lines(temp_image, points):\n", " \"\"\"Draw lines between interpolated points on the first, third, second, and fourth edges\"\"\"\n", " if len(points) == 4:\n", " # Intervals for the first-third edge connection\n", " edge1_points = [interpolate(points[0], points[1], t) for t in INTERVV]\n", " edge3_points = [interpolate(points[2], points[3], 1 - t) for t in INTERVV]\n", " for p1, p3 in zip(edge1_points, edge3_points):\n", " cv2.line(temp_image, tuple(p1), tuple(p3), (0, 255, 255), 1)\n", "\n", " # Intervals for the second-fourth edge connection\n", " edge2_points = [interpolate(points[1], points[2], t) for t in INTERVH]\n", " edge4_points = [interpolate(points[3], points[0], 1 - t) for t in INTERVH]\n", " for p2, p4 in zip(edge2_points, edge4_points):\n", " cv2.line(temp_image, tuple(p2), tuple(p4), (255, 0, 255), 1)\n", " return temp_image\n", "\n", " def draw_polygon(temp_image, points, closed=False):\n", " if len(points) > 1:\n", " color = (0, 255, 0) if not closed else (255, 0, 0)\n", " cv2.polylines(temp_image, [np.array(points, np.int32)], closed, color, 2)\n", " for point in points:\n", " cv2.circle(temp_image, tuple(point), 5, (0, 0, 255), -1)\n", " temp_image = draw_additional_lines(temp_image, points)\n", " return temp_image\n", "\n", " def mouse_events(event, x, y, flags, param):\n", " nonlocal points, moving, current_point_index, image, original_image\n", " if event == cv2.EVENT_LBUTTONDOWN:\n", " for i, point in enumerate(points):\n", " if abs(x - point[0]) < 5 and abs(y - point[1]) < 5:\n", " moving = True\n", " current_point_index = i\n", " return\n", " if len(points) < 4:\n", " points.append([x, y])\n", " image = draw_polygon(\n", " original_image.copy(), points, closed=(len(points) == 4)\n", " )\n", "\n", " elif event == cv2.EVENT_MOUSEMOVE:\n", " if moving and current_point_index != -1:\n", " points[current_point_index] = [x, y]\n", " image = draw_polygon(\n", " original_image.copy(), points, closed=(len(points) == 4)\n", " )\n", "\n", " elif event == cv2.EVENT_LBUTTONUP:\n", " moving = False\n", " current_point_index = -1\n", "\n", " cv2.namedWindow(window_name)\n", " cv2.setMouseCallback(window_name, mouse_events)\n", "\n", " # Main loop\n", " while True:\n", " cv2.imshow(window_name, image)\n", " key = cv2.waitKey(1) & 0xFF\n", " if key == 13: # Enter key\n", " cv2.destroyAllWindows()\n", " return points # Return the coordinates when Enter is pressed\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "metadata": {} }, "outputs": [], "source": [ "def warp_polygon(image_path, polygon_points):\n", " \"\"\"Warps the quadrilateral defined by polygon_points into a rectangle.\"\"\"\n", "\n", " image = cv2.imread(image_path)\n", " image = cv2.flip(image, 1)\n", "\n", " pts_src = np.array(polygon_points).astype(np.float32)\n", "\n", " # Define points in destination (output rectangle) image\n", " width = 200 # Width of the rectangle\n", " height = 50 # Height of the rectangle\n", " pts_dst = np.array(\n", " [[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]]\n", " ).astype(np.float32)\n", "\n", " # Calculate the perspective transform matrix\n", " matrix = cv2.getPerspectiveTransform(pts_src, pts_dst)\n", "\n", " # Warp the image\n", " warped_image = cv2.warpPerspective(image, matrix, (width, height))\n", " return warped_image\n", "\n", "\n", "def extract_line_pixels(warped_image, intervalsV, intervalsH):\n", " \"\"\"Extracts pixel data along vertical and horizontal lines at given intervals.\"\"\"\n", " height, width, channels = warped_image.shape\n", "\n", " pixel_data = []\n", "\n", " # Vertical lines\n", " for i in intervalsV:\n", " x_coord = int(width * i)\n", " vertical_line = warped_image[:, x_coord, 1]\n", " pixel_data.append(vertical_line)\n", "\n", " # Horizontal lines\n", " for i in intervalsH:\n", " y_coord = int(height * i)\n", " horizontal_line = warped_image[y_coord, :, 1]\n", " pixel_data.append(horizontal_line)\n", "\n", " return pixel_data\n" ] }, { "cell_type": "markdown", "metadata": { "metadata": {} }, "source": [ "import matplotlib.pyplot as plt\n", "\n", "fig, axes = plt.subplots(3, 5, figsize=(15, 15))\n", "axes = axes.flatten()\n", "for i, pixels in enumerate(data):\n", "axes[i].plot(pixels)\n", "axes[i].set_ylim([0, 255])\n", "axes[i].set_title(f\"Line {i+1}\")\n", "axes[i].set_xlabel(\"Pixel Index\")\n", "axes[i].set_ylabel(\"Pixel Value\")\n", "\n", "plt.tight_layout()\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "metadata": {} }, "outputs": [], "source": [ "def peaks(data, boxes=2):\n", " # split data in boxes\n", " data = np.array_split(data, boxes)\n", "\n", " # get the maximum value in each box\n", " data = [np.max(d) for d in data]\n", " data = [d > 150 for d in data]\n", " return np.array(data).astype(int).tolist()\n", "\n", "\n", "digits = {\n", " 0: [[1, 0, 1], [1, 1], [1, 1]],\n", " 1: [[0, 0, 0], [0, 1], [0, 1]],\n", " 2: [[1, 1, 1], [0, 1], [1, 0]],\n", " 3: [[1, 1, 1], [0, 1], [0, 1]],\n", " 4: [[0, 1, 0], [1, 1], [0, 1]],\n", " 5: [[1, 1, 1], [1, 0], [0, 1]],\n", " 6: [[1, 1, 1], [1, 0], [1, 1]],\n", " 7: [[1, 0, 0], [0, 1], [0, 1]],\n", " 8: [[1, 1, 1], [1, 1], [1, 1]],\n", " 9: [[1, 1, 1], [1, 1], [0, 1]],\n", "}\n", "\n", "\n", "def OCRdigit(vertical, horizontal1, horizontal2):\n", " # get times it goes above 150, remove subsequent values\n", " digit = [peaks(vertical, 3), peaks(horizontal1), peaks(horizontal2)]\n", " digit = [key for key, value in digits.items() if value == digit]\n", " return digit[0]\n", "\n", "\n", "def OCRscreen(pixels_along_lines):\n", " data = (\n", " pixels_along_lines[:5]\n", " + [\n", " pixels_along_lines[5][:40],\n", " pixels_along_lines[5][40:80],\n", " pixels_along_lines[5][80:120],\n", " pixels_along_lines[5][120:160],\n", " pixels_along_lines[5][160:],\n", " ]\n", " + [\n", " pixels_along_lines[6][:40],\n", " pixels_along_lines[6][40:80],\n", " pixels_along_lines[6][80:120],\n", " pixels_along_lines[6][120:160],\n", " pixels_along_lines[6][160:],\n", " ]\n", " )\n", "\n", " text = \"\"\n", " for i in range(5):\n", " text += str(OCRdigit(data[i], data[i + 5], data[i + 10]))\n", " return text\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "metadata": {} }, "outputs": [], "source": [ "from datetime import datetime\n", "import xlsxwriter\n", "\n", "\n", "def writeDate(worksheet, row, column, date, format):\n", " original_format = \"%Y-%m-%d %H-%M-%S-%f\"\n", " parsed_datetime = datetime.strptime(date, original_format)\n", "\n", " worksheet.write_datetime(row, column, parsed_datetime, format)\n", "\n", "\n", "def data2excel(data):\n", " # save the data in an excel file\n", " fileName = \"data.xlsx\"\n", " workbook = xlsxwriter.Workbook(fileName)\n", " worksheet = workbook.add_worksheet()\n", "\n", " dateFormat = workbook.add_format({\"num_format\": \"dd/mm/yy hh:mm:ss\"})\n", "\n", " # write the data\n", " row = 0\n", " for key, value in data.items():\n", " date = key.split(\" \", 1)[1][:-4]\n", " writeDate(worksheet, row, 0, date, dateFormat)\n", " worksheet.write(row, 1, value)\n", " try:\n", " worksheet.write(row, 2, float(value[:6]))\n", " except Exception as _:\n", " pass\n", " row += 1\n", "\n", " workbook.close()\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "metadata": {} }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Error processing bandicam 2024-04-16 11-25-10-700.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-40-00-733.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-40-10-720.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-44-30-732.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-48-20-723.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-48-30-728.jpg: list index out of range\n", "Error processing bandicam 2024-04-16 11-49-50-741.jpg: list index out of range\n" ] } ], "source": [ "folder = (\n", " \"./2/\"\n", ")\n", "images = [f for f in os.listdir(folder) if f.endswith(\".jpg\")]\n", "\n", "region = draw_interactive_polygon(folder + images[0])\n", "\n", "data = {}\n", "for image in images:\n", " try:\n", " warped = warp_polygon(folder + image, region)\n", " pixels_along_lines = extract_line_pixels(warped, INTERVV, INTERVH)\n", " data[image] = OCRscreen(pixels_along_lines)\n", " except Exception as e:\n", " print(f\"Error processing {image}: {e}\")\n", " continue\n", "\n", "data2excel(data)\n" ] } ], "metadata": { "kernelspec": { "display_name": "AI_logging", "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.14" } }, "nbformat": 4, "nbformat_minor": 2 }