Spaces:
Build error
Build error
import numpy as np | |
from typing import List | |
from PIL import Image | |
import cv2 | |
import numpy.typing as npt | |
from numpy import uint8 | |
ImageType = npt.NDArray[uint8] | |
from numpy.typing import NDArray | |
# not used actually | |
def get_rotate_crop_image(img: ImageType, points:NDArray[np.float32])-> ImageType: | |
""" | |
Points should be ordered in this order :left_lower, right_lower, right_upper, left_upper | |
each point has 2 coordinate | |
So entire thing is np array of size 4 times 2 with float32 numbers | |
takes an image and a set of four points defining a quadrilateral region within the image. | |
It extracts and crops this region, corrects its orientation using a perspective transform, | |
and rotates it if necessary. | |
""" | |
assert len(points) == 4 | |
# Check the shape and dtype of points | |
assert points.shape == (4, 2), f"Points array must be of shape (4, 2), but got {points.shape}" | |
assert points.dtype == np.float32, f"Points array must be of dtype float32, but got {points.dtype}" | |
# Calculating Crop Dimensions | |
img_crop_width = int( | |
max( | |
np.linalg.norm(points[0] - points[1]), | |
np.linalg.norm(points[2] - points[3]))) | |
img_crop_height = int( | |
max( | |
np.linalg.norm(points[0] - points[3]), | |
np.linalg.norm(points[1] - points[2]))) | |
#A set of standard points pts_std is defined to represent the corners of the cropped image in a straightened, upright rectangle. | |
pts_std = np.float32([[0, 0], [img_crop_width, 0], | |
[img_crop_width, img_crop_height], | |
[0, img_crop_height]]) | |
# perspective transformation matrix M that maps the four points to the standard rectangle. | |
M = cv2.getPerspectiveTransform(points, pts_std) | |
#applies the perspective transformation to the image, using the transformation matrix M | |
dst_img = cv2.warpPerspective( | |
img, | |
M, (img_crop_width, img_crop_height), | |
borderMode=cv2.BORDER_REPLICATE, | |
flags=cv2.INTER_CUBIC) | |
dst_img_height, dst_img_width = dst_img.shape[0:2] | |
if dst_img_height * 1.0 / dst_img_width >= 1.5: | |
#rotating counter clock wise | |
dst_img = np.rot90(dst_img) | |
#correct would be k=3 | |
#st_img = np.rot90(dst_img,k=3) | |
return dst_img | |
def get_crop_image(img: ImageType, points:NDArray[np.float32],straight=False)-> ImageType: | |
""" | |
Points should be ordered in this order :left_lower, right_lower, right_upper, left_upper | |
each point has 2 coordinate | |
So entire thing is np array of size 4 times 2 with float32 numbers | |
takes an image and a set of four points defining a quadrilateral region within the image. | |
It extracts and crops this region. No perspective transformation is applied | |
""" | |
assert len(points) == 4 # xmin, ymin, xmax, ymax | |
# Check the shape and dtype of points | |
assert points.shape == (4, 2), f"Points array must be of shape (4, 2), but got {points.shape}" | |
assert points.dtype == np.float32, f"Points array must be of dtype float32, but got {points.dtype}" | |
if not straight : | |
img_crop_width = int( | |
max( | |
np.linalg.norm(points[0] - points[1]), | |
np.linalg.norm(points[2] - points[3]))) | |
img_crop_height = int( | |
max( | |
np.linalg.norm(points[0] - points[3]), | |
np.linalg.norm(points[1] - points[2]))) | |
# bottom left corner | |
xmin = int(points[0][0]) | |
ymin = int(points[0][1]) | |
# Ensure the crop area is within the bounds of the image | |
xmax = min(xmin + img_crop_width, img.shape[1]) | |
ymax = min(ymin + img_crop_height, img.shape[0]) | |
else: | |
xmin = int(points[0][0]) | |
ymin = int(points[0][1]) | |
xmax = int(points[2][0]) | |
ymax = int(points[2][1]) | |
# Crop the image | |
dst_img = img[ymin:ymax, xmin:xmax] | |
return dst_img | |
def cropImages(bxs:List[NDArray[np.float32]], img:Image.Image,straight=False) -> List[ImageType] : | |
images_to_recognizer = [] | |
for bnum in range(len(bxs)): | |
left_lower, right_lower, right_upper, left_upper = bxs[bnum] | |
box = np.array([left_lower, right_lower, right_upper, left_upper ]) | |
cropped_img = get_crop_image(np.array(img), box, straight) | |
images_to_recognizer.append(cropped_img) | |
# return list of np arrays | |
return images_to_recognizer | |
def crop_an_Image(box:NDArray[np.float32], img:Image.Image) -> ImageType : | |
#box should be 4x2 array | |
left_lower, right_lower, right_upper, left_upper = box | |
b = np.array([left_lower, right_lower, right_upper, left_upper ]) | |
cropped_img = get_crop_image(np.array(img), b) | |
return cropped_img | |
def get_new_coord(maxx:int,maxy:int,points:NDArray[np.float32]) -> list[int]: | |
#points = 4x2 array | |
img_crop_width = int( | |
max( | |
np.linalg.norm(points[0] - points[1]), | |
np.linalg.norm(points[2] - points[3]))) | |
img_crop_height = int( | |
max( | |
np.linalg.norm(points[0] - points[3]), | |
np.linalg.norm(points[1] - points[2]))) | |
# bottom left corner | |
bottom_left_x = int(points[0][0]) | |
bottom_left_y = int(points[0][1]) | |
# Ensure the crop area is within the bounds of the image | |
top_right_x = min(bottom_left_x + img_crop_width, maxx) | |
top_right_y = min(bottom_left_y + img_crop_height, maxy) | |
# Crop the image | |
# 4x1 array of xmin, ymin, xmax, ymax | |
return [bottom_left_x, bottom_left_y, top_right_x, top_right_y] | |
MARGIN_FACTOR = 1.4 | |
def get_crop_image_with_extra_margin(img: ImageType, points:NDArray[np.float32],straight=False, marginfactor = MARGIN_FACTOR)-> ImageType: | |
""" | |
Points should be ordered in this order :left_lower, right_lower, right_upper, left_upper | |
each point has 2 coordinate | |
So entire thing is np array of size 4 times 2 with float32 numbers | |
takes an image and a set of four points defining a quadrilateral region within the image. | |
It extracts and crops this region, corrects its orientation using a perspective transform, | |
and rotates it if necessary. | |
""" | |
assert len(points) == 4 | |
# Calculating Crop Dimensions | |
if not straight : | |
img_crop_width = int( | |
max( | |
np.linalg.norm(points[0] - points[1]), | |
np.linalg.norm(points[2] - points[3]))) | |
img_crop_height = int( | |
max( | |
np.linalg.norm(points[0] - points[3]), | |
np.linalg.norm(points[1] - points[2]))) | |
# bottom left corner | |
xmin = int(points[0][0]) | |
ymin = int(points[0][1]) | |
# Ensure the crop area is within the bounds of the image | |
xmax = min(xmin + img_crop_width, img.shape[1]) | |
ymax = min(ymin + img_crop_height, img.shape[0]) | |
else: | |
xmin = int(points[0][0]) | |
ymin = int(points[0][1]) | |
xmax = int(points[2][0]) | |
ymax = int(points[2][1]) | |
#print("points are "+str(points)) | |
#print("xmin, ymin, xmax,ymax are "+ str(xmin)+" "+ str(ymin)+" "+ str(xmax)+" "+str(ymax)) | |
# Crop the image | |
dst_img = img[ymin:ymax, xmin:xmax] | |
#print(dst_img.shape[:2]) | |
height, width = dst_img.shape[:2] | |
if width/height<1.6: | |
bigger = max(height,width) | |
new_height = int(bigger *3) | |
new_width = int(bigger*3) | |
else: | |
bigger = max(height,width) | |
new_height = int(bigger *MARGIN_FACTOR) | |
new_width = int(bigger*MARGIN_FACTOR) | |
# Create a new image with a white background | |
new_img = np.full((new_height, new_width, 3), fill_value=255, dtype=np.uint8) # RGB white background | |
# Calculate the position to center the image on the new white background | |
y_offset = (new_height - height) // 2 | |
x_offset = (new_width - width) // 2 | |
#print("offsets are " + str(x_offset)+" " +str(y_offset)) | |
# Place the warped image on the new white background | |
new_img[y_offset:y_offset + height, x_offset:x_offset+width] = dst_img | |
return new_img | |
def cropImageExtraMargin(bxs:List[NDArray[np.float32]], img:Image.Image,straight=False, margin = MARGIN_FACTOR ) -> List[ImageType] : | |
images_to_recognizer = [] | |
for bnum in range(len(bxs)): | |
left_lower, right_lower, right_upper, left_upper = bxs[bnum] | |
box = np.array([left_lower, right_lower, right_upper, left_upper ]) | |
#print("newbox is") | |
#print(box) | |
cropped_img = get_crop_image_with_extra_margin(np.array(img), box,straight,margin) | |
images_to_recognizer.append(cropped_img) | |
# return list of np arrays | |
return images_to_recognizer |