
2 changed files with 0 additions and 320 deletions
@ -1,230 +0,0 @@ |
|||
package com.visual.open.anpr.core.models; |
|||
|
|||
import ai.onnxruntime.OnnxTensor; |
|||
import ai.onnxruntime.OrtSession; |
|||
import com.visual.open.anpr.core.base.BaseOnnxInfer; |
|||
import com.visual.open.anpr.core.base.PlateDetection; |
|||
import com.visual.open.anpr.core.clipper.Clipper; |
|||
import com.visual.open.anpr.core.clipper.ClipperOffset; |
|||
import com.visual.open.anpr.core.clipper.Path; |
|||
import com.visual.open.anpr.core.clipper.Paths; |
|||
import com.visual.open.anpr.core.domain.ImageMat; |
|||
import com.visual.open.anpr.core.domain.PlateInfo; |
|||
import com.visual.open.anpr.core.domain.Polygon; |
|||
import com.visual.open.anpr.core.utils.ReleaseUtil; |
|||
import org.opencv.core.*; |
|||
import org.opencv.imgproc.Imgproc; |
|||
|
|||
import java.util.*; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public class PaddlePlateDetection extends BaseOnnxInfer implements PlateDetection { |
|||
|
|||
private float thresh=0.3f; |
|||
private float box_thresh=0.6f; |
|||
private int max_candidates=1000; |
|||
private float unclip_ratio=1.5f; |
|||
private float min_size = 3f; |
|||
|
|||
private float[] std = {0.229f, 0.224f, 0.225f}; |
|||
private Scalar mean = new Scalar(0.485, 0.456, 0.406); |
|||
|
|||
public PaddlePlateDetection(String modelPath, int threads) { |
|||
super(modelPath, threads); |
|||
} |
|||
|
|||
@Override |
|||
public List<PlateInfo> inference(ImageMat image, float scoreTh, float iouTh, Map<String, Object> params) { |
|||
OnnxTensor tensor = null; |
|||
OrtSession.Result output = null; |
|||
ImageMat imageMat = image.clone(); |
|||
try { |
|||
//前置处理
|
|||
tensor = imageMat |
|||
.blobFromImageAndDoReleaseMat(1.0/255, this.mean, true) |
|||
.to4dFloatOnnxTensorAndNoReleaseMat(this.std,true); |
|||
//ONNX推理
|
|||
output = getSession().run(Collections.singletonMap(getInputName(), tensor)); |
|||
float[][][][] result = (float[][][][]) output.get(0).getValue(); |
|||
//模型后处理
|
|||
List<PlateInfo> plateInfos = new ArrayList<>(); |
|||
for (float[][] item : result[0]){ |
|||
List<PlateInfo> list = this.dbPostProcess(item, image.getWidth(), image.getHeight()); |
|||
if(!list.isEmpty()){ |
|||
plateInfos.addAll(list); |
|||
} |
|||
} |
|||
//返回
|
|||
return plateInfos; |
|||
}catch (Exception e){ |
|||
throw new RuntimeException(e); |
|||
}finally { |
|||
if(null != tensor){ |
|||
ReleaseUtil.release(tensor); |
|||
} |
|||
if(null != output){ |
|||
ReleaseUtil.release(output); |
|||
} |
|||
if(null != imageMat){ |
|||
ReleaseUtil.release(imageMat); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 后处理 |
|||
* @param pred |
|||
* @param destWidth |
|||
* @param destHeight |
|||
* @return |
|||
*/ |
|||
private List<PlateInfo> dbPostProcess(float[][] pred, int destWidth, int destHeight){ |
|||
//初始化Mat
|
|||
Mat rawMat = Mat.zeros(pred.length,pred[0].length, CvType.CV_8UC1); |
|||
Mat maskMat = Mat.zeros(pred.length,pred[0].length, CvType.CV_8UC1); |
|||
int width = rawMat.width(); int height = rawMat.height(); |
|||
//添加数据
|
|||
for(int i=0; i< pred.length; i++){ |
|||
for(int j=0; j<pred[i].length; j++ ){ |
|||
rawMat.put(i, j, pred[i][j]); |
|||
maskMat.put(i, j, pred[i][j] >= thresh ? 255 : 0); |
|||
} |
|||
} |
|||
//边缘提取
|
|||
final List<MatOfPoint> points = new ArrayList<>(); |
|||
final Mat hierarchy = new Mat(); |
|||
Imgproc.findContours(maskMat, points, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); |
|||
//遍历边缘
|
|||
List<PlateInfo> list = new ArrayList<>(); |
|||
int numContours = Math.min(points.size(), max_candidates); |
|||
for(int i=0; i<numContours; i++){ |
|||
MatOfPoint contour = points.get(i); |
|||
PlateInfo res = getMiniBoxes(contour); |
|||
if(res.score < this.min_size){ |
|||
continue; |
|||
} |
|||
//获取边缘线的最大最小坐标
|
|||
int h = maskMat.size(0); |
|||
int w = maskMat.size(1); |
|||
PlateInfo.Point []box = res.box.toArray(); |
|||
int xmin = clip(Arrays.stream(box).mapToInt((item) -> Double.valueOf(Math.floor(item.x)).intValue()).min().getAsInt(), 0, w-1); |
|||
int xmax = clip(Arrays.stream(box).mapToInt((item) -> Double.valueOf(Math.ceil(item.x)).intValue()).max().getAsInt(), 0, w-1); |
|||
int ymin = clip(Arrays.stream(box).mapToInt((item) -> Double.valueOf(Math.floor(item.y)).intValue()).min().getAsInt(), 0, h-1); |
|||
int ymax = clip(Arrays.stream(box).mapToInt((item) -> Double.valueOf(Math.ceil(item.y)).intValue()).max().getAsInt(), 0, h-1); |
|||
Mat mask = Mat.zeros(ymax - ymin + 1,xmax - xmin + 1, CvType.CV_8UC1); |
|||
//组织多边形的蒙版数据
|
|||
List<Point> boxPoints = Arrays.stream(box).map((item)-> new Point(item.x, item.y)).collect(Collectors.toList()); |
|||
List<Point> boxPointList = Arrays.stream(box).map((item)-> new Point(item.x-xmin, item.y-ymin)).collect(Collectors.toList()); |
|||
MatOfPoint matOfPoint = new MatOfPoint(); |
|||
matOfPoint.fromList(boxPointList); |
|||
List<MatOfPoint> ptsoo = Collections.singletonList(matOfPoint); |
|||
//数据填充
|
|||
Imgproc.fillPoly(mask, ptsoo, Scalar.all(1)); |
|||
Scalar scalar = Core.mean(new Mat(rawMat, new Rect( xmin, ymin, xmax + 1 -xmin, ymax + 1-ymin)), mask); |
|||
float score = (float) scalar.val[0]; |
|||
if(this.box_thresh > score){ |
|||
continue; |
|||
} |
|||
//多边形的距离计算
|
|||
Polygon polygon = new Polygon(boxPoints); |
|||
double distance = polygon.getArea() * unclip_ratio / polygon.getLength(); |
|||
//线和多边形的裁剪和偏移
|
|||
Path path = new Path(); |
|||
for(Point u : boxPoints){ |
|||
path.add(new com.visual.open.anpr.core.clipper.Point.LongPoint((long) u.x, (long)u.y)); |
|||
} |
|||
Paths paths = new Paths(); |
|||
ClipperOffset offset = new ClipperOffset(); |
|||
offset.addPath(path, Clipper.JoinType.ROUND, Clipper.EndType.CLOSED_POLYGON); |
|||
offset.execute(paths, distance); |
|||
//重新获取边缘线
|
|||
MatOfPoint contour1 = new MatOfPoint(); |
|||
List<Point> poo= paths.get(0).stream().map(item -> new Point(item.getX(), item.getY())).collect(Collectors.toList()); |
|||
contour1.fromList(poo); |
|||
//重新提取边缘线
|
|||
PlateInfo res1 = getMiniBoxes(contour1); |
|||
if(res1.score < this.min_size+2){ |
|||
continue; |
|||
} |
|||
//添加一点偏移量
|
|||
int offsetWidth = (int) (res1.box.width() * 0.00f); |
|||
int offsetHeight = (int) (res1.box.height() * 0.00f); |
|||
//组装返回信息
|
|||
PlateInfo r = PlateInfo.build(score, PlateInfo.PlateBox.build( |
|||
PlateInfo.Point.build( |
|||
clip(Math.round(res1.box.leftTop.x / width * destWidth) - offsetWidth, 0, destWidth), |
|||
clip(Math.round(res1.box.leftTop.y / height * destHeight) - offsetHeight, 0, destHeight)), |
|||
PlateInfo.Point.build( |
|||
clip(Math.round(res1.box.rightTop.x / width * destWidth) + offsetWidth, 0, destWidth), |
|||
clip(Math.round(res1.box.rightTop.y / height * destHeight) - offsetHeight, 0, destHeight)), |
|||
PlateInfo.Point.build( |
|||
clip(Math.round(res1.box.rightBottom.x / width * destWidth) + offsetWidth, 0, destWidth), |
|||
clip(Math.round(res1.box.rightBottom.y / height * destHeight) + offsetHeight, 0, destHeight)), |
|||
PlateInfo.Point.build( |
|||
clip(Math.round(res1.box.leftBottom.x / width * destWidth) - offsetWidth, 0, destWidth), |
|||
clip(Math.round(res1.box.leftBottom.y / height * destHeight) + offsetHeight, 0, destHeight)) |
|||
)); |
|||
list.add(r); |
|||
} |
|||
|
|||
return list; |
|||
} |
|||
|
|||
|
|||
public PlateInfo getMiniBoxes(MatOfPoint contour){ |
|||
MatOfPoint2f pts = new MatOfPoint2f(); |
|||
pts.fromList(contour.toList()); |
|||
RotatedRect rect = Imgproc.minAreaRect(pts); |
|||
|
|||
Mat yyy = new Mat(); |
|||
Imgproc.boxPoints(rect, yyy); |
|||
|
|||
List<Point> cs = new ArrayList<>(); |
|||
for (int m=0; m< yyy.size().height; m++){ |
|||
Point ccc = new Point(yyy.get(m, 0)[0], yyy.get(m, 1)[0]); |
|||
cs.add(ccc); |
|||
} |
|||
Collections.sort(cs, Comparator.comparingDouble(o -> o.x)); |
|||
|
|||
int index_1 = 0; |
|||
int index_2 = 1; |
|||
int index_3 = 2; |
|||
int index_4 = 3; |
|||
|
|||
if(cs.get(1).y > cs.get(0).y){ |
|||
index_1 = 0; |
|||
index_4 = 1; |
|||
}else{ |
|||
index_1 = 1; |
|||
index_4 = 0; |
|||
} |
|||
|
|||
if(cs.get(3).y > cs.get(2).y){ |
|||
index_2 = 2; |
|||
index_3 = 3; |
|||
}else{ |
|||
index_2 = 3; |
|||
index_3 = 2; |
|||
} |
|||
|
|||
double sside = Math.min(rect.size.height, rect.size.width); |
|||
PlateInfo.PlateBox plateBox = PlateInfo.PlateBox.build( |
|||
PlateInfo.Point.build((float) cs.get(index_1).x, (float)cs.get(index_1).y), |
|||
PlateInfo.Point.build((float) cs.get(index_2).x, (float)cs.get(index_2).y), |
|||
PlateInfo.Point.build((float) cs.get(index_3).x, (float)cs.get(index_3).y), |
|||
PlateInfo.Point.build((float) cs.get(index_4).x, (float)cs.get(index_4).y) |
|||
); |
|||
return PlateInfo.build((float)sside, plateBox); |
|||
} |
|||
|
|||
public static int clip(int value, int min, int max){ |
|||
if(value > max){ |
|||
return max; |
|||
} |
|||
if(value < min){ |
|||
return min; |
|||
} |
|||
return value; |
|||
} |
|||
|
|||
} |
@ -1,90 +0,0 @@ |
|||
package com.visual.open.anpr.core.models; |
|||
|
|||
import com.visual.open.anpr.core.domain.DrawImage; |
|||
import com.visual.open.anpr.core.domain.ImageMat; |
|||
import com.visual.open.anpr.core.domain.PlateInfo; |
|||
import org.opencv.imgcodecs.Imgcodecs; |
|||
|
|||
import java.awt.*; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
|
|||
public class PaddlePlateDetectionTest { |
|||
|
|||
public static void main(String[] args) { |
|||
PaddlePlateDetection detection = new PaddlePlateDetection("open-anpr-core/src/main/resources/models/model3.onnx", 1); |
|||
|
|||
String imagePath = "open-anpr-core/src/test/resources/images/image010.jpg"; |
|||
for(int wi=1; wi <=128; wi++){ |
|||
for(int wy=3; wy>=0;wy--){ |
|||
int width = wi * 32 - wy; |
|||
for(int hi=1; hi <=128; hi++) { |
|||
for (int hy = 3; hy >= 0; hy--) { |
|||
int height = hi * 32 - hy; |
|||
ImageMat imageMat = null; |
|||
try { |
|||
imageMat = ImageMat.fromImage(imagePath).resizeAndDoReleaseMat(width, height); |
|||
List<PlateInfo> plateInfos = detection.inference(imageMat, 1,1, new HashMap<>()); |
|||
System.out.println(plateInfos); |
|||
System.out.println("success:"+width+":"+height); |
|||
}catch (Throwable t){ |
|||
System.out.println("error:"+width+":"+height); |
|||
}finally { |
|||
if(imageMat != null){ |
|||
imageMat.release(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
// for(int w=351; w <=351; w++){
|
|||
// for(int h=351; h <=351; h++){
|
|||
// ImageMat imageMat = null;
|
|||
// try {
|
|||
// imageMat = ImageMat.fromImage(imagePath).resizeAndDoReleaseMat(w, h);
|
|||
// List<PlateInfo> plateInfos = detection.inference(imageMat, 1,1, new HashMap<>());
|
|||
// System.out.println(plateInfos);
|
|||
// System.out.println("success:"+w+":"+h);
|
|||
// }catch (Throwable t){
|
|||
// System.out.println("error:"+w+":"+h);
|
|||
// }finally {
|
|||
// if(imageMat != null){
|
|||
// imageMat.release();
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
// String image1Path = "open-anpr-core/src/test/resources/images/imagetmp.jpg";
|
|||
// Imgcodecs.imwrite(image1Path, imageMat.toCvMat());
|
|||
|
|||
|
|||
// DrawImage drawImage = DrawImage.build(image1Path);
|
|||
// for(PlateInfo plateInfo : plateInfos){
|
|||
// PlateInfo.Point [] points = plateInfo.box.toArray();
|
|||
// for(int i =0; i< points.length; i++){
|
|||
// if(i+1 == points.length){
|
|||
// drawImage.drawLine(
|
|||
// new DrawImage.Point((int)points[i].x, (int)points[i].y),
|
|||
// new DrawImage.Point((int)points[0].x, (int)points[0].y),
|
|||
// 2, Color.RED
|
|||
// );
|
|||
// }else{
|
|||
// drawImage.drawLine(
|
|||
// new DrawImage.Point((int)points[i].x, (int)points[i].y),
|
|||
// new DrawImage.Point((int)points[i+1].x, (int)points[i+1].y),
|
|||
// 2, Color.RED
|
|||
// );
|
|||
// }
|
|||
// }
|
|||
// }
|
|||
// ImageMat.fromCVMat(drawImage.toMat()).imShow();
|
|||
} |
|||
} |
Loading…
Reference in new issue