AI_logging/img2xlsx2.ipynb

346 lines
12 KiB
Plaintext

{
"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
}