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
|
import numpy as np
import cv2
import math
def square(num):
return num*num
class Rect:
def __init__(self, x_min, x_max, y_min, y_max):
self.x_min = x_min
self.x_max = x_max
self.y_min = y_min
self.y_max = y_max
def __repr__(self):
return "x: " + np.str(self.x_min) + " ~ " + np.str(self.x_max) + " y: " + np.str(self.y_min) + " ~ " + np.str(self.y_max) + "\n"
def __str__(self):
return "x: " + np.str(self.x_min) + " ~ " + np.str(self.x_max) + " y: " + np.str(self.y_min) + " ~ " + np.str(self.y_max) + "\n"
def distance(self, point):
dis = 0
if point[0] < self.x_min:
dis += self.x_min - point[0]
elif point[0] > self.x_max:
dis += point[0] - self.x_max
if point[1] < self.y_min:
dis += self.y_min - point[1]
elif point[1] > self.y_max:
dis += point[1] - self.y_max
return dis
def distance_math(self, point):
dis = 0
if point[0] < self.x_min:
dis += square(self.x_min - point[0])
elif point[0] > self.x_max:
dis += square(point[0] - self.x_max)
if point[1] < self.y_min:
dis += square(self.y_min - point[1])
elif point[1] > self.y_max:
dis += square(point[1] - self.y_max)
return math.sqrt(dis)
def center(self):
return [(self.x_min+self.x_max)/2, (self.y_min+self.y_max)/2]
def line_to_rect(line):
x_min=x_max=y_min=y_max=-1
for point in line:
if x_min == -1:
x_min = x_max = point[0][0]
y_min = y_max = point[0][1]
else:
x_min = min(x_min, point[0][0])
x_max = max(x_max, point[0][0])
y_min = min(y_min, point[0][1])
y_max = max(y_max, point[0][1])
return Rect(x_min, x_max, y_min, y_max)
def remove_non_rect(width, height, contours):
rects = []
for line in contours:
_r=line_to_rect(line)
if _r.x_min < 20 or _r.y_min < 20 or _r.x_max > width-20 or _r.y_max > height-20:
continue
xd = _r.x_max-_r.x_min
yd = _r.y_max-_r.y_min
if min(xd, yd) < 15:
continue
diff = 10
xmin = _r.x_min + diff
xmax = _r.x_max - diff
ymin = _r.y_min + diff
ymax = _r.y_max - diff
for point in line:
if xmin < point[0][0] < xmax and ymin < point[0][1] < ymax:
diff = -1
break
if diff != -1:
rects.append(_r)
return rects
def read_file(filename):
img=cv2.imread(filename)
return img
def process_img(img):
grey=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
retval,grey=cv2.threshold(grey,80,255,cv2.THRESH_BINARY_INV)
grey=cv2.erode(grey,None)
grey=cv2.dilate(grey,None)
_,contours,hierarchy=cv2.findContours(grey,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
rows,cols,ch = img.shape
return img, remove_non_rect(cols, rows, contours)
def calculate_distance(width, height, rect):
return [rect.distance([0,0]), rect.distance([width,0]), rect.distance([0,height]), rect.distance([width,height])]
def find_corner_points(width, height, rects):
result = [None, None, None, None]
distance = [None, None, None, None]
for rect in rects:
if result[0] is None:
result = [rect, rect, rect, rect]
distance = calculate_distance(width, height, rect)
else:
_dis = calculate_distance(width, height, rect)
for i in range(4):
if _dis[i] < distance[i]:
distance[i] = _dis[i]
result[i] = rect
return result
def draw_rects(img, rects, output):
print(img.shape)
rows = img.shape[0]
cols = img.shape[1]
img = img[:]
for index,rect in enumerate(rects):
img = cv2.rectangle(img, (rect.x_min,rect.y_min), (rect.x_max,rect.y_max), (0,255,0), 3)
img = cv2.putText(img,str(index),(rect.x_max+5,rect.y_max+5), cv2.FONT_HERSHEY_SIMPLEX, 2,(255,255,0), 3)
points = find_corner_points(cols, rows, rects)
if len(rects) > 0:
for rect in points:
img = cv2.rectangle(img, (rect.x_min,rect.y_min), (rect.x_max,rect.y_max), (0,255,255), 5)
#cv2.imshow('hello', img)
cv2.imwrite(output + ".png", img)
cv2.waitKey(0)
def fix_image(img, rects):
rows,cols,ch = img.shape
points = find_corner_points(cols, rows, rects)
tl = points[0]
tl_c = tl.center()
tr = points[1]
tr_c = tr.center()
bl = points[2]
bl_c = bl.center()
pts1 = np.float32([tl_c, tr_c, bl_c])
pts2 = np.float32([tl_c, [tl_c[0] + tl.distance_math(tr_c), tl_c[1]], [tl_c[0], tl_c[1] + tl.distance_math(bl_c)]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
return dst
def remove_rects(rects, x_min, x_max, y_min, y_max):
valid_rects = []
for rect in rects:
if x_min < rect.x_max < x_max and y_min < rect.y_max < y_max or x_min < rect.x_min < x_max and y_min < rect.y_min < y_max:
continue
valid_rects.append(rect)
return valid_rects
|