init commit
This commit is contained in:
163
extract_data.py
Normal file
163
extract_data.py
Normal file
@@ -0,0 +1,163 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import cv2 as cv
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import pytesseract as tess
|
||||
from PIL import Image
|
||||
|
||||
PHOTOS_PATH = "./photos/"
|
||||
|
||||
|
||||
# Get a list of images given a directory path
|
||||
def get_images(url: str):
|
||||
images = []
|
||||
for img_url in os.listdir(url):
|
||||
try:
|
||||
image = Image.open(os.path.join(url, img_url))
|
||||
images.append(image)
|
||||
except IOError:
|
||||
print(f"Error opening image: {img_url}")
|
||||
return images
|
||||
|
||||
|
||||
# Get the datetime taken from an image
|
||||
def get_datetime_taken(image: Image.Image) -> datetime | None:
|
||||
exif = image.getexif()
|
||||
if 306 in exif:
|
||||
return datetime.strptime(exif[306], "%Y:%m:%d %H:%M:%S")
|
||||
return None
|
||||
|
||||
|
||||
# Convert an image to OpenCV format
|
||||
def convert_to_opencv_image(img: Image.Image) -> np.ndarray:
|
||||
return cv.cvtColor(np.array(img), cv.COLOR_RGB2BGR)
|
||||
|
||||
|
||||
def order_points(pts):
|
||||
pts = pts.reshape(4, 2)
|
||||
rect = np.zeros((4, 2), dtype="float32")
|
||||
|
||||
s = pts.sum(axis=1)
|
||||
rect[0] = pts[np.argmin(s)] # top-left
|
||||
rect[2] = pts[np.argmax(s)] # bottom-right
|
||||
|
||||
diff = np.diff(pts, axis=1)
|
||||
rect[1] = pts[np.argmin(diff)] # top-right
|
||||
rect[3] = pts[np.argmax(diff)] # bottom-left
|
||||
|
||||
return rect
|
||||
|
||||
|
||||
def is_closed_contour(cnt, eps=1.0):
|
||||
# Check area
|
||||
if cv.contourArea(cnt) == 0:
|
||||
return False
|
||||
# Check if first and last points are close
|
||||
return cv.norm(cnt[0][0] - cnt[-1][0]) < eps
|
||||
|
||||
|
||||
# Optimise the image for OCR
|
||||
def process_image(img: Image.Image):
|
||||
arr = convert_to_opencv_image(img)
|
||||
|
||||
# Blur the image for better edge (contour) detection
|
||||
blur = cv.GaussianBlur(arr, (7, 7), 0)
|
||||
edges = cv.Canny(blur, 50, 100)
|
||||
contours, hierarchy = cv.findContours(
|
||||
edges, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE
|
||||
)
|
||||
|
||||
# Filter contours for rectangles
|
||||
candidates = []
|
||||
img_area = arr.shape[0] * arr.shape[1]
|
||||
|
||||
for cnt in contours:
|
||||
rect = cv.minAreaRect(cnt)
|
||||
(center, (width, height), angle) = rect
|
||||
box = cv.boxPoints(rect)
|
||||
box_contour = box.reshape((-1, 1, 2))
|
||||
area = cv.contourArea(box_contour)
|
||||
if area < 0.01 * img_area:
|
||||
continue
|
||||
# Check the aspect ratio is reasonable
|
||||
aspect_ratio = width / float(height)
|
||||
|
||||
if 0.9 < aspect_ratio < 1.1:
|
||||
candidates.append(box_contour)
|
||||
|
||||
# Most likely rectangle will be the largest one
|
||||
if len(candidates) == 0:
|
||||
return None
|
||||
|
||||
cv.drawContours(arr, contours, -1, (0, 255, 0), 3)
|
||||
preview_image(arr)
|
||||
|
||||
display_contour = max(candidates, key=cv.contourArea)
|
||||
rect = order_points(display_contour)
|
||||
(w, h) = (400, 400)
|
||||
dst = np.array([[0, 0], [w - 1, 0], [w - 1, h - 1], [0, h - 1]], dtype="float32")
|
||||
mat = cv.getPerspectiveTransform(rect, dst)
|
||||
warped = cv.warpPerspective(arr, mat, (w, h))
|
||||
return warped
|
||||
|
||||
|
||||
# Get the text from an image using OCR
|
||||
def ocr_image(img: Image.Image) -> str:
|
||||
return None
|
||||
|
||||
|
||||
# Process OCR text output
|
||||
def process_ocr_text(text: str) -> str:
|
||||
return None
|
||||
|
||||
|
||||
# There are two gyms that I go to, one is the Peckham gym and the other is the Elephant and Castle gym.
|
||||
# You can tell which gym I went to by looking at the color of the wall.
|
||||
# If there is a green wall, its most likely the Peckham gym.
|
||||
# If there is a blue wall, its most likely the Elephant and Castle gym.
|
||||
def get_gym(image: Image.Image) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
def preview_image(img: np.ndarray):
|
||||
cv.imshow("preview", img)
|
||||
cv.waitKey(0)
|
||||
cv.destroyAllWindows()
|
||||
|
||||
|
||||
def __main__():
|
||||
imgs = get_images(PHOTOS_PATH)
|
||||
|
||||
if not imgs:
|
||||
print("No images")
|
||||
return None
|
||||
|
||||
fail = []
|
||||
success = []
|
||||
for img in imgs:
|
||||
tst = process_image(img)
|
||||
if tst is None:
|
||||
fail.append(img.filename)
|
||||
continue
|
||||
|
||||
success.append(img.filename)
|
||||
print("success_len: ", len(success))
|
||||
print("fail_len: ", len(fail))
|
||||
|
||||
print("failed:")
|
||||
for x in fail:
|
||||
print(x)
|
||||
|
||||
print("success:")
|
||||
for x in success:
|
||||
print(x)
|
||||
|
||||
print("success_len: ", len(success))
|
||||
print("fail_len: ", len(fail))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
__main__()
|
||||
Reference in New Issue
Block a user