diff --git a/img2xlsx.ipynb b/img2xlsx.ipynb index 93cb411..f475d1e 100644 --- a/img2xlsx.ipynb +++ b/img2xlsx.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "metadata": {} }, @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": { "metadata": {} }, @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": { "metadata": {} }, @@ -115,7 +115,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": { "metadata": {} }, @@ -125,34 +125,273 @@ "output_type": "stream", "text": [ "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n", - "list index out of range\n" + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n", + "index 0 is out of bounds for axis 1 with size 0\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[1;32mIn[5], line 24\u001b[0m\n\u001b[0;32m 22\u001b[0m image_path \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(folder, image_name)\n\u001b[0;32m 23\u001b[0m image \u001b[38;5;241m=\u001b[39m cv2\u001b[38;5;241m.\u001b[39mimread(image_path)\n\u001b[1;32m---> 24\u001b[0m sheared_image \u001b[38;5;241m=\u001b[39m \u001b[43mshear_img\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimage\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 26\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m idx, region \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28menumerate\u001b[39m(regions):\n\u001b[0;32m 27\u001b[0m target_path \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mjoin(cropped_folder, \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mimage_name[:\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m4\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m_\u001b[39m\u001b[38;5;132;01m{\u001b[39;00midx\u001b[38;5;241m+\u001b[39m\u001b[38;5;241m1\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.jpg\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "Cell \u001b[1;32mIn[2], line 11\u001b[0m, in \u001b[0;36mshear_img\u001b[1;34m(image)\u001b[0m\n\u001b[0;32m 9\u001b[0m M \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39mfloat32([[\u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m0.22\u001b[39m, \u001b[38;5;241m0\u001b[39m], [\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m0\u001b[39m], [\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m]])\n\u001b[0;32m 10\u001b[0m sheared_img \u001b[38;5;241m=\u001b[39m cv2\u001b[38;5;241m.\u001b[39mwarpPerspective(image, M, (\u001b[38;5;28mint\u001b[39m(cols \u001b[38;5;241m*\u001b[39m \u001b[38;5;241m1.5\u001b[39m), \u001b[38;5;28mint\u001b[39m(rows \u001b[38;5;241m*\u001b[39m \u001b[38;5;241m1.5\u001b[39m)))\n\u001b[1;32m---> 11\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcv2\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mflip\u001b[49m\u001b[43m(\u001b[49m\u001b[43msheared_img\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[1;31mKeyboardInterrupt\u001b[0m: " ] } ], "source": [ - "folder = \"../../../Downloads/wetransfer_metingen-8-04-tot-15-40-5min_2024-04-15_0905/metingen 8-04 tot 15-40 (5min)/\"\n", + "folder = \"./wetransfer_metingen-16-04-1200-1300_2024-04-16_1102/metingen 16-04 (1200-1300)/\"\n", "images = [f for f in os.listdir(folder) if f.endswith(\".jpg\")]\n", "cropped_folder = os.path.join(folder, \"cropped\")\n", "os.makedirs(cropped_folder, exist_ok=True)\n", @@ -193,7 +432,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "metadata": {} }, @@ -204,7 +443,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "metadata": {} }, diff --git a/img2xlsx.py b/img2xlsx.py index d9a2d8f..039f29f 100644 --- a/img2xlsx.py +++ b/img2xlsx.py @@ -1,35 +1,195 @@ -from paddleocr import PaddleOCR import os +from datetime import datetime + import cv2 +import numpy as np import xlsxwriter - -def ocr_image(image_path, ocr): - result = ocr.ocr(image_path, cls=True) - return result[0][0][1][0] +INTERVV = [0.09, 0.29, 0.5, 0.7, 0.91] +INTERVH = [0.33, 0.6] -def cropUI(image_path): - # small opencv window to crop the image +def draw_interactive_polygon(image_path): + # Initialize variables + points = [] + moving = False + current_point_index = -1 + + original_image = cv2.flip(cv2.imread(image_path), 1) + image = original_image.copy() + window_name = "Polygon Drawer" + + def interpolate(p1, p2, t): + """Linearly interpolate between points p1 and p2 with parameter t""" + return [int((1 - t) * p1[0] + t * p2[0]), int((1 - t) * p1[1] + t * p2[1])] + + def draw_additional_lines(temp_image, points): + """Draw lines between interpolated points on the first, third, second, and fourth edges""" + if len(points) == 4: + # Intervals for the first-third edge connection + edge1_points = [interpolate(points[0], points[1], t) for t in INTERVV] + edge3_points = [interpolate(points[2], points[3], 1 - t) for t in INTERVV] + for p1, p3 in zip(edge1_points, edge3_points): + cv2.line(temp_image, tuple(p1), tuple(p3), (0, 255, 255), 1) + + # Intervals for the second-fourth edge connection + edge2_points = [interpolate(points[1], points[2], t) for t in INTERVH] + edge4_points = [interpolate(points[3], points[0], 1 - t) for t in INTERVH] + for p2, p4 in zip(edge2_points, edge4_points): + cv2.line(temp_image, tuple(p2), tuple(p4), (255, 0, 255), 1) + return temp_image + + def draw_polygon(temp_image, points, closed=False): + if len(points) > 1: + color = (0, 255, 0) if not closed else (255, 0, 0) + cv2.polylines(temp_image, [np.array(points, np.int32)], closed, color, 2) + for point in points: + cv2.circle(temp_image, tuple(point), 5, (0, 0, 255), -1) + temp_image = draw_additional_lines(temp_image, points) + return temp_image + + def mouse_events(event, x, y, flags, param): + nonlocal points, moving, current_point_index, image, original_image + if event == cv2.EVENT_LBUTTONDOWN: + for i, point in enumerate(points): + if abs(x - point[0]) < 5 and abs(y - point[1]) < 5: + moving = True + current_point_index = i + return + if len(points) < 4: + points.append([x, y]) + image = draw_polygon( + original_image.copy(), points, closed=(len(points) == 4) + ) + + elif event == cv2.EVENT_MOUSEMOVE: + if moving and current_point_index != -1: + points[current_point_index] = [x, y] + image = draw_polygon( + original_image.copy(), points, closed=(len(points) == 4) + ) + + elif event == cv2.EVENT_LBUTTONUP: + moving = False + current_point_index = -1 + + cv2.namedWindow(window_name) + cv2.setMouseCallback(window_name, mouse_events) + + # Main loop + while True: + cv2.imshow(window_name, image) + key = cv2.waitKey(1) & 0xFF + if key == 13: # Enter key + cv2.destroyAllWindows() + return points # Return the coordinates when Enter is pressed + + +def warp_polygon(image_path, polygon_points): + """Warps the quadrilateral defined by polygon_points into a rectangle.""" + image = cv2.imread(image_path) - r = cv2.selectROI(image) - cv2.destroyAllWindows() + image = cv2.flip(image, 1) - return r + pts_src = np.array(polygon_points).astype(np.float32) + + # Define points in destination (output rectangle) image + width = 200 # Width of the rectangle + height = 50 # Height of the rectangle + pts_dst = np.array( + [[0, 0], [width - 1, 0], [width - 1, height - 1], [0, height - 1]] + ).astype(np.float32) + + # Calculate the perspective transform matrix + matrix = cv2.getPerspectiveTransform(pts_src, pts_dst) + + # Warp the image + warped_image = cv2.warpPerspective(image, matrix, (width, height)) + return warped_image -def cropImage(image_path, r, flip, cropped_folder): - # crop the image and save it - image = cv2.imread(image_path) - cropped = image[int(r[1]) : int(r[1] + r[3]), int(r[0]) : int(r[0] + r[2])] +def extract_line_pixels(warped_image, intervalsV, intervalsH): + """Extracts pixel data along vertical and horizontal lines at given intervals.""" + height, width, channels = warped_image.shape - # save with new name - if flip == "y": - cropped = cv2.flip(cropped, 1) + pixel_data = [] - # save in subfolder cropped - new_name = os.path.join(cropped_folder, image_path.split("/")[-1]) - cv2.imwrite(new_name, cropped) + # Vertical lines + for i in intervalsV: + x_coord = int(width * i) + vertical_line = warped_image[:, x_coord, 1] + pixel_data.append(vertical_line) + + # Horizontal lines + for i in intervalsH: + y_coord = int(height * i) + horizontal_line = warped_image[y_coord, :, 1] + pixel_data.append(horizontal_line) + + return pixel_data + + +def peaks(data, boxes=2): + # split data in boxes + data = np.array_split(data, boxes) + + # get the maximum value in each box + data = [np.max(d) for d in data] + data = [d > 150 for d in data] + return np.array(data).astype(int).tolist() + + +digits = { + 0: [[1, 0, 1], [1, 1], [1, 1]], + 1: [[0, 0, 0], [0, 1], [0, 1]], + 2: [[1, 1, 1], [0, 1], [1, 0]], + 3: [[1, 1, 1], [0, 1], [0, 1]], + 4: [[0, 1, 0], [1, 1], [0, 1]], + 5: [[1, 1, 1], [1, 0], [0, 1]], + 6: [[1, 1, 1], [1, 0], [1, 1]], + 7: [[1, 0, 0], [0, 1], [0, 1]], + 8: [[1, 1, 1], [1, 1], [1, 1]], + 9: [[1, 1, 1], [1, 1], [0, 1]], +} + + +def OCRdigit(vertical, horizontal1, horizontal2): + # get times it goes above 150, remove subsequent values + digit = [peaks(vertical, 3), peaks(horizontal1), peaks(horizontal2)] + digit = [key for key, value in digits.items() if value == digit] + return digit[0] + + +def OCRscreen(pixels_along_lines): + data = ( + pixels_along_lines[:5] + + [ + pixels_along_lines[5][:40], + pixels_along_lines[5][40:80], + pixels_along_lines[5][80:120], + pixels_along_lines[5][120:160], + pixels_along_lines[5][160:], + ] + + [ + pixels_along_lines[6][:40], + pixels_along_lines[6][40:80], + pixels_along_lines[6][80:120], + pixels_along_lines[6][120:160], + pixels_along_lines[6][160:], + ] + ) + + text = "" + for i in range(5): + text += str(OCRdigit(data[i], data[i + 5], data[i + 10])) + return text + + +def writeDate(worksheet, row, column, date, format): + original_format = "%Y-%m-%d %H-%M-%S-%f" + parsed_datetime = datetime.strptime(date, original_format) + + worksheet.write_datetime(row, column, parsed_datetime, format) def data2excel(data): @@ -38,11 +198,13 @@ def data2excel(data): workbook = xlsxwriter.Workbook(fileName) worksheet = workbook.add_worksheet() + dateFormat = workbook.add_format({"num_format": "dd/mm/yy hh:mm:ss"}) + # write the data row = 0 for key, value in data.items(): date = key.split(" ", 1)[1][:-4] - worksheet.write(row, 0, date) + writeDate(worksheet, row, 0, date, dateFormat) worksheet.write(row, 1, value) try: worksheet.write(row, 2, float(value[:6])) @@ -54,43 +216,23 @@ def data2excel(data): def main(): - # ocr settings - os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" - ocr = PaddleOCR(use_angle_cls=True, lang="en") + folder = "./" + images = [f for f in os.listdir(folder) if f.endswith(".jpg")] - # *** start GUIs *** - images = [f for f in os.listdir(FOLDER) if f.endswith(".jpg")] - region = cropUI(os.path.join(FOLDER, images[0])) + region = draw_interactive_polygon(folder + images[0]) - flip = input("Do you want to flip the images horizontaly? (y/n): ") - - cropped_folder = os.path.join(FOLDER, "cropped") - if not os.path.exists(cropped_folder): - os.makedirs(cropped_folder) - - # *** start cropping *** - for image in images: - cropImage(os.path.join(FOLDER, image), region, flip, cropped_folder) - - # *** start OCR *** - cropped_images = [f for f in os.listdir(cropped_folder) if f.endswith(".jpg")] data = {} - for image in cropped_images: + for image in images: try: - path = os.path.join(cropped_folder, image) - text = ocr_image(path, ocr) - except Exception as _: - print("Error in cropped image") + warped = warp_polygon(folder + image, region) + pixels_along_lines = extract_line_pixels(warped, INTERVV, INTERVH) + data[image] = OCRscreen(pixels_along_lines) + except Exception as e: + print(f"Error processing {image}: {e}") continue - data[image] = text - - # *** save data in excel *** data2excel(data) - print("All images cropped successfully") - if __name__ == "__main__": - FOLDER = "data/" main() diff --git a/img2xlsx2.ipynb b/img2xlsx2.ipynb new file mode 100644 index 0000000..2f332b4 --- /dev/null +++ b/img2xlsx2.ipynb @@ -0,0 +1,345 @@ +{ + "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 +}