Spaces:
Sleeping
Sleeping
File size: 7,430 Bytes
1b8cf5d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
import fitz # PyMuPDF
import cv2
import numpy as np
import pandas as pd
import os
import uuid
import pypdfium2 as pdfium
from PIL import Image
def convert2img(path):
pdf = pdfium.PdfDocument(path)
page = pdf.get_page(0)
pil_image = page.render().to_pil()
pl1=np.array(pil_image)
img = cv2.cvtColor(pl1, cv2.COLOR_RGB2BGR)
return img
def save_image(img):
filename = f"{uuid.uuid4().hex}.png"
path = os.path.join("/tmp", filename)
cv2.imwrite(path, img)
return filename
def threshold(imgResult3):
#gaus4 = cv2.GaussianBlur(imgResult3, (3,3),9)
blur = cv2.blur(imgResult3,(7,7))
gray4 = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
outsu4 = cv2.threshold(gray4, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
return outsu4
def get_columns_info(outsu4, img):
mask_clmns = np.ones(img.shape[:2], dtype="uint8") * 255
mask_walls = np.ones(img.shape[:2], dtype="uint8") * 255
contours, hierarchy = cv2.findContours(image=outsu4, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE)
p = [] #to save points of each contour
for i, cnt in enumerate(contours):
M = cv2.moments(cnt)
if M['m00'] != 0.0:
x1 = int(M['m10']/M['m00'])
y1 = int(M['m01']/M['m00'])
area = cv2.contourArea(cnt)
if area > (881.0*2):
perimeter = cv2.arcLength(cnt,True)
#print(perimeter)
cv2.drawContours(mask_walls, [cnt], -1, 0, -1)
if area < (881.0 * 2) and area > 90:
# maybe make it area < (881.0 * 1.5)
p.append((x1,y1))
#print(area)
cv2.drawContours(mask_clmns, [cnt], -1, 0, -1)
return p, mask_clmns, mask_walls
def get_text_from_pdf(input_pdf_path):
pdf_document = fitz.open(input_pdf_path)
results = []
for page_num in range(pdf_document.page_count):
page = pdf_document[page_num]
width, height = page.rect.width, page.rect.height # Get page dimensions
text_instances = [word for word in page.get_text("words") if word[4].startswith(("C", "c")) and len(word[4]) <= 5]
page.apply_redactions()
return text_instances
def calculate_midpoint(x1,y1,x2,y2):
xm = int((x1 + x2) / 2)
ym = int((y1 + y2) / 2)
return (xm, ym)
def getTextsPoints(x):
point_list = []
pt_clm = {}
for h in x:
#point_list.append(calculate_midpoint(h[1],h[0],h[3],h[2]))
#pt_clm[calculate_midpoint(h[1],h[0],h[3],h[2])] = h[4]
point_list.append(calculate_midpoint(h[0],h[1],h[2],h[3]))
pt_clm[calculate_midpoint(h[0],h[1],h[2],h[3])] = h[4]
return point_list, pt_clm
def fix_90_ky_val(pt_clm, derotationMatrix):
new_derotated = {}
for ky in pt_clm:
pts = fitz.Point(ky[0], ky[1]) * derotationMatrix
new_ky = ((int(pts.y),int(pts.x)))
new_derotated[new_ky] = pt_clm[ky]
return new_derotated
def distance(point1, point2):
x1, y1 = point1
x2, y2 = point2
return np.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
def getNearestText(point_list, p):
nearbyy = []
selected_clm_point = [] #save the clmn for drawing cirlce on it
dis = []
txt_clmn = []
for i in range(len(p)):
nearest_point = min(point_list, key=lambda point: distance(point, p[i]))
dist = distance(nearest_point, p[i])
dis.append(dist)
#if dist < 10:
nearbyy.append(nearest_point)
selected_clm_point.append(p[i])
txt_clmn.append((nearest_point, p[i]))
return nearbyy, selected_clm_point, txt_clmn
def fix_rotation_90(pc_coordinates, derotationMatrix):
coor = []
for coordinate in pc_coordinates:
pts = fitz.Point(coordinate[0], coordinate[1]) * derotationMatrix
coor.append((int(pts.y),int(pts.x)))
return coor
def color_groups(txtpts_ky_vlu):
import random
unique_labels = list(set(txtpts_ky_vlu.values()))
def generate_rgb():
return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) # RGB tuple
key_colors = {key: generate_rgb() for key in unique_labels} # Assign a unique RGB color to each key
return key_colors
def getColumnsTypesKeyValue(nearbyy, pt_clm):
words = []
for i in range(len(nearbyy)):
words.append(pt_clm[nearbyy[i]])
return words
def generate_legend(found_tuple):
word_freq = {}
for word in found_tuple:
if word in word_freq:
word_freq[word] += 1
else:
word_freq[word] = 1
data = word_freq
df = pd.DataFrame(data.items(), columns=['Column Type', 'Count'])
return df
def get_drawing_info(txt_clmn,txtpts_ky_vlu,key_colors):
#Search for each word in the txt_clmn to get the word associated to it
huge_list_clmn_clr_loc = []
for text_location, column_location in txt_clmn:
word = txtpts_ky_vlu[text_location]
huge_list_clmn_clr_loc.append((text_location, column_location, word, key_colors[word]))
return huge_list_clmn_clr_loc #text_location, column_location, word, color
def get_columns_info2(outsu4, img):
mask_clmns = np.ones(img.shape[:2], dtype="uint8") * 255
mask_walls = np.ones(img.shape[:2], dtype="uint8") * 255
contours, hierarchy = cv2.findContours(image=outsu4, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
p_column = [] #to save midpoints of each column
p_wall = [] #to save midpoints of each wall
wall_contour = []
all_points = []
wall_mid_and_full = {}
for i, cnt in enumerate(contours):
M = cv2.moments(cnt)
if M['m00'] != 0.0:
x1 = int(M['m10']/M['m00'])
y1 = int(M['m01']/M['m00'])
area = cv2.contourArea(cnt)
if area > (881.0):
perimeter = cv2.arcLength(cnt,True)
p_wall.append((x1,y1))
#print(perimeter)
cv2.drawContours(mask_walls, [cnt], -1, 0, -1)
wall_contour.append(cnt)
all_points.append((x1,y1))
wall_mid_and_full[(x1, y1)] = cnt
if area < (881.0 * 2) and area > 90:
# maybe make it area < (881.0 * 1.5)
all_points.append((x1,y1))
p_column.append((x1,y1))
#print(area)
cv2.drawContours(mask_clmns, [cnt], -1, 0, -1)
wall_mid_and_full[(x1, y1)] = cnt
return p_column, p_wall, mask_clmns, mask_walls, wall_contour, all_points, wall_mid_and_full
def get_all_wall_points(wall_contours):
all_contours = []
for cnt in wall_contours:
contour_points = [(int(point[0][0]), int(point[0][1])) for point in cnt]
all_contours.append(contour_points)
return all_contours
def get_text_wall_text(input_pdf_path):
pdf_document = fitz.open(input_pdf_path)
results = []
for page_num in range(pdf_document.page_count):
page = pdf_document[page_num]
width, height = page.rect.width, page.rect.height
text_instances = [word for word in page.get_text("words") if word[4].startswith(("w", "W")) and len(word[4]) <= 5]
page.apply_redactions()
return text_instances
import math
def distance(p1, p2):
return math.hypot(p1[0] - p2[0], p1[1] - p2[1])
def assign_walls_to_texts(text_locations, wall_locations, threshold=55):
matched_texts = []
matched_walls = []
text_wall_pairs = []
for text in text_locations:
nearest_wall = min(wall_locations, key=lambda wall: distance(wall, text))
dist = distance(nearest_wall, text)
print(f"Text {text} -> Nearest wall {nearest_wall}, Distance: {dist:.2f}")
if dist < threshold:
matched_texts.append(text)
matched_walls.append(nearest_wall)
text_wall_pairs.append((text, nearest_wall))
return matched_texts, matched_walls, text_wall_pairs
|