cimo001's picture
update
345568c verified
Raw
History Blame Contribute Delete
4.74 kB
import sys
sys.dont_write_bytecode = True
import cv2
import numpy
import pyclipper
from helper import onnxSessionBuild
pathModel = "./PP-OCRv6_medium_det/"
limitSideLength = 960
limitSideLengthMax = 4000
binaryThreshold = 0.2
boxThreshold = 0.45
unclipRatio = 1.4
candidateMax = 3000
sideMinimum = 3
meanList = numpy.array([0.485, 0.456, 0.406], dtype=numpy.float32)
standardList = numpy.array([0.229, 0.224, 0.225], dtype=numpy.float32)
onnxSession = onnxSessionBuild(f"{pathModel}onnx/pp-ocrV6_medium_det.onnx")
def imageResize(image):
imageHeight, imageWidth = image.shape[0:2]
ratio = 1.0
if max(imageHeight, imageWidth) > limitSideLength:
if imageHeight > imageWidth:
ratio = float(limitSideLength) / imageHeight
else:
ratio = float(limitSideLength) / imageWidth
resizeHeight = int(imageHeight * ratio)
resizeWidth = int(imageWidth * ratio)
if max(resizeHeight, resizeWidth) > limitSideLengthMax:
ratio = float(limitSideLengthMax) / max(resizeHeight, resizeWidth)
resizeHeight = int(resizeHeight * ratio)
resizeWidth = int(resizeWidth * ratio)
resizeHeight = max(int(round(resizeHeight / 32) * 32), 32)
resizeWidth = max(int(round(resizeWidth / 32) * 32), 32)
return cv2.resize(image, (resizeWidth, resizeHeight))
def boxOrder(contour):
rectangle = cv2.minAreaRect(contour)
pointList = sorted(list(cv2.boxPoints(rectangle)), key=lambda point: point[0])
index1 = 0
index2 = 1
index3 = 2
index4 = 3
if pointList[1][1] > pointList[0][1]:
index1 = 0
index4 = 1
else:
index1 = 1
index4 = 0
if pointList[3][1] > pointList[2][1]:
index2 = 2
index3 = 3
else:
index2 = 3
index3 = 2
return [pointList[index1], pointList[index2], pointList[index3], pointList[index4]], min(rectangle[1])
def boxScore(probabilityMap, box):
mapHeight, mapWidth = probabilityMap.shape[0:2]
boxLocal = box.copy()
xMinimum = max(0, min(int(numpy.floor(box[:, 0].min())), mapWidth - 1))
xMaximum = max(0, min(int(numpy.ceil(box[:, 0].max())), mapWidth - 1))
yMinimum = max(0, min(int(numpy.floor(box[:, 1].min())), mapHeight - 1))
yMaximum = max(0, min(int(numpy.ceil(box[:, 1].max())), mapHeight - 1))
mask = numpy.zeros((yMaximum - yMinimum + 1, xMaximum - xMinimum + 1), dtype=numpy.uint8)
boxLocal[:, 0] = boxLocal[:, 0] - xMinimum
boxLocal[:, 1] = boxLocal[:, 1] - yMinimum
cv2.fillPoly(mask, boxLocal.reshape(1, -1, 2).astype(numpy.int32), 1)
return cv2.mean(probabilityMap[yMinimum:yMaximum + 1, xMinimum:xMaximum + 1], mask)[0]
def boxUnclip(box):
area = cv2.contourArea(box)
length = cv2.arcLength(box, True)
distance = area * unclipRatio / length
offsetObject = pyclipper.PyclipperOffset()
offsetObject.AddPath(box, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
return numpy.array(offsetObject.Execute(distance))
def inference(image):
resultList = []
imageHeight, imageWidth = image.shape[0:2]
imageResized = imageResize(image)
tensor = (imageResized.astype(numpy.float32) / 255.0 - meanList) / standardList
tensor = numpy.expand_dims(tensor.transpose((2, 0, 1)), axis=0).astype(numpy.float32)
tensorOutputList = onnxSession.run(None, {"x": tensor})
probabilityMap = tensorOutputList[0][0][0]
bitmap = (probabilityMap > binaryThreshold).astype(numpy.uint8)
scaleWidth = imageWidth / float(bitmap.shape[1])
scaleHeight = imageHeight / float(bitmap.shape[0])
contourList, hierarchy = cv2.findContours(bitmap * 255, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for a in range(min(len(contourList), candidateMax)):
pointList, sideLength = boxOrder(contourList[a])
if sideLength < sideMinimum:
continue
score = boxScore(probabilityMap, numpy.array(pointList).reshape(-1, 2))
if score < boxThreshold:
continue
pointList, sideLength = boxOrder(boxUnclip(numpy.array(pointList)).reshape(-1, 1, 2))
if sideLength < sideMinimum + 2:
continue
coordinateList = []
for b in range(len(pointList)):
x = max(0, min(int(round(pointList[b][0] * scaleWidth)), imageWidth))
y = max(0, min(int(round(pointList[b][1] * scaleHeight)), imageHeight))
coordinateList.append([x, y])
resultList.append({
"score": score,
"coordinate": coordinateList
})
return resultList
image = cv2.imread(sys.argv[1])
itemList = inference(image)
for a in range(len(itemList)):
print(f"{itemList[a]['score']:.6f} | {itemList[a]['coordinate']}")