diff --git a/.classpath b/.classpath
index 481b25f4057e2add50feaa9fb2664155a4d31594..136685672d01d4c8354c99513a8711750df586e3 100644
--- a/.classpath
+++ b/.classpath
@@ -1,19 +1,20 @@
+
+
+
+
-
-
-
-
+
diff --git a/pom.xml b/pom.xml
index 2f09fb010481cb29ba77ece314edfe25340e839a..ee04f5ebadc16d2746742e8c3d163be4368ee0c6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,11 +38,5 @@
poi-ooxml
4.1.2
-
-
- org.openpnp
- opencv
- 4.3.0-2
-
\ No newline at end of file
diff --git a/src/test/java/com/hy/java/uct/umlrecog/OpenCVTest.java b/src/test/java/com/hy/java/uct/umlrecog/OpenCVTest.java
index ea86df7832f1b06d78073283c84a726653db9b8e..fb1f370aa52230dccad6eddf7791f478e948508a 100644
--- a/src/test/java/com/hy/java/uct/umlrecog/OpenCVTest.java
+++ b/src/test/java/com/hy/java/uct/umlrecog/OpenCVTest.java
@@ -3,6 +3,7 @@ package com.hy.java.uct.umlrecog;
import java.util.ArrayList;
import java.util.List;
+import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
@@ -11,117 +12,136 @@ import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
-import nu.pattern.OpenCV;
+import com.hy.java.utility.common.Pair;
public class OpenCVTest {
- static String image_path = "D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\eclipse.jetty-class diagram.png";
+ static String class_diagram_path = "D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\eclipse.jetty-class diagram.png";
public static void main(String[] args) {
// TODO Auto-generated method stub
- OpenCV.loadShared();
- // System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+ System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 读取图片。并灰度处理
- Mat mat = Imgcodecs.imread(image_path, Imgcodecs.IMREAD_GRAYSCALE);
+ Mat mat = Imgcodecs.imread(class_diagram_path, Imgcodecs.IMREAD_GRAYSCALE);
// 高斯锐化,提升类图图形清晰度
// Imgproc.Laplacian(mat, mat, 2);
// 二值化,用于后续处理
Imgproc.threshold(mat, mat, 160, 255, Imgproc.THRESH_BINARY);
// 矩形检测
- detectRec(mat);
+ Pair> rec_detected = detectRec(mat);
+ // 关系类型检测
+ Mat temp = detectRelationType(rec_detected);
// 直线检测
- // detectLines(mat);
- // 看一眼
- // Imgcodecs.imwrite("D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\result.png",mat);
+ detectLines(temp);
}
- private static void detectRec(Mat src) {
+ /**
+ * 检测方框
+ *
+ * @param src
+ * @return
+ */
+ private static Pair> detectRec(Mat src) {
// TODO Auto-generated method stub
+ System.out.println("识别所有类");
+ List class_rects = new ArrayList<>();
+ // 识别图中所有“轮廓”并保存
List contours = new ArrayList<>();
Imgproc.findContours(src, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
- for (MatOfPoint c : contours) {
- if (Imgproc.contourArea(c) < 10) {
+ // 对每个轮廓,检测是否为矩形
+ for (MatOfPoint contour : contours) {
+ // 如果轮廓面积太小或太大,则直接忽略。阈值可以根据图片像素动态计算
+ if (Imgproc.contourArea(contour) < 10 || Imgproc.contourArea(contour) > 100000) {
continue;
}
-
- MatOfPoint2f curve = new MatOfPoint2f(c.toArray());
- MatOfPoint2f approxCurve = new MatOfPoint2f();
- // 轮廓逼近
+ // 如果轮廓面积合适,则检测是否为矩形。采用多边形逼近法
+ MatOfPoint2f curve = new MatOfPoint2f(contour.toArray());
+ MatOfPoint2f approx_curve = new MatOfPoint2f();
+ // 将轮廓向多边形做逼近
double epsilon = 0.01 * Imgproc.arcLength(curve, true);
- Imgproc.approxPolyDP(curve, approxCurve, epsilon, true);
-// System.out.print(approxCurve.dump());
- // Drawing lines on the image
- if (approxCurve.toArray().length == 4) {
- System.out.println(approxCurve.dump());
- double[] data1 = approxCurve.get(0, 0);
- double[] data2 = approxCurve.get(1, 0);
- double[] data3 = approxCurve.get(2, 0);
- double[] data4 = approxCurve.get(3, 0);
- Point pt1 = new Point(data1[0], data1[1]);
- Point pt2 = new Point(data2[0], data2[1]);
- Point pt3 = new Point(data3[0], data3[1]);
- Point pt4 = new Point(data4[0], data4[1]);
+ Imgproc.approxPolyDP(curve, approx_curve, epsilon, true);
+ // 如果逼近的多边形一共有4个顶点,则可以认为是矩形(其实应该再检查4个顶点的坐标)。将检测结果绘制在原图中
+ if (approx_curve.toArray().length == 4) {
+ // 将每个矩形存在别处用于识别文字。存完后将其从图中抹掉,防止其干扰直线识别
+ class_rects.add(contour);
+ // 将矩形从图中抹掉(涂白)。后面还需对所有边框进行涂白
+ Imgproc.fillConvexPoly(src, contour, new Scalar(255, 255, 255));
+ // 已下几行其实无用,只是提示如何获取矩形顶点
+ // 4个顶点
+ Point pt1 = new Point(approx_curve.get(0, 0)[0], approx_curve.get(0, 0)[1]);
+ Point pt2 = new Point(approx_curve.get(1, 0)[0], approx_curve.get(1, 0)[1]);
+ Point pt3 = new Point(approx_curve.get(2, 0)[0], approx_curve.get(2, 0)[1]);
+ Point pt4 = new Point(approx_curve.get(3, 0)[0], approx_curve.get(3, 0)[1]);
Imgproc.line(src, pt1, pt2, new Scalar(187, 255, 255), 2);
Imgproc.line(src, pt2, pt3, new Scalar(187, 255, 255), 2);
Imgproc.line(src, pt3, pt4, new Scalar(187, 255, 255), 2);
Imgproc.line(src, pt4, pt1, new Scalar(187, 255, 255), 2);
}
- System.out.println("<<<<<<<<<<<<<<<<<");
-// double[] data;
-// double rho, theta;
-// Point pt1 = new Point();
-// Point pt2 = new Point();
-// double a, b;
-// double x0, y0;
-//
-// for (int i = 0; i < approxCurve.rows(); i = i + 4) {
-//
-// data = approxCurve.get(i, 0);
-// pt1.x = data[0];
-// pt1.y = data[1];
-// pt2.x = data[2];
-// pt2.y = data[3];
-// Imgproc.line(src, pt1, pt2, new Scalar(187, 255, 255), 20);
-// }
- // Writing the image
- // Imgcodecs.imwrite("D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\result.png",
- // src);
-
}
-
- // Imgproc.drawContours(src, contours, -1, new Scalar(0, 0, 255), 1);
- // Writing the image
+ // 对所有边框进行涂白
+ Imgproc.drawContours(src, class_rects, -1, new Scalar(255, 255, 255), 8);
+ // 将图片写入result文件
Imgcodecs.imwrite("D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\result.png", src);
+ System.out.println("识别类完毕,共" + class_rects.size() + "个");
+ return Pair.createPair(src, class_rects);
+ }
+
+ /**
+ * 识别关系符号
+ *
+ * @param rec_detected
+ * @return
+ */
+ private static Mat detectRelationType(Pair> rec_detected) {
+ // TODO Auto-generated method stub
+ System.out.println("识别所有关系符号");
+ List class_rects = new ArrayList<>();
+ // 识别图中所有“轮廓”并保存
+ List contours = new ArrayList<>();
+ Imgproc.findContours(rec_detected.getLeft(), contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);
+ // 对每个轮廓,检测是否为“特殊形状”
+ for (MatOfPoint contour : contours) {
+ // 如果轮廓面积太小或太大,则直接忽略。阈值可以根据图片像素动态计算
+ if (Imgproc.contourArea(contour) < 35 || Imgproc.contourArea(contour) > 1000) {
+ continue;
+ }
+ // 如果轮廓面积合适,则检测是否为关系符号形状。采用多边形逼近法
+ MatOfPoint2f curve = new MatOfPoint2f(contour.toArray());
+ MatOfPoint2f approx_curve = new MatOfPoint2f();
+ // 将轮廓向多边形做逼近
+ double epsilon = 0.01 * Imgproc.arcLength(curve, true);
+ Imgproc.approxPolyDP(curve, approx_curve, epsilon, true);
+ System.out.print(approx_curve.dump());
+ // 将每个关系符号存在别处。存完后将其从图中抹掉,防止其干扰直线识别
+ class_rects.add(contour);
+ // 将关系符号从图中抹掉(涂白)。后面还需对所有边框进行涂白
+ Imgproc.fillConvexPoly(rec_detected.getLeft(), contour, new Scalar(15, 225, 25));
+ }
+ // 对所有边框进行涂白
+ Imgproc.drawContours(rec_detected.getLeft(), class_rects, -1, new Scalar(255, 255, 255), 8);
+ // 将图片写入result文件
+ Imgcodecs.imwrite("D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\result.png", rec_detected.getLeft());
+ System.out.println("识别关系符号完毕,共" + class_rects.size() + "个");
+ return rec_detected.getLeft();
}
private static void detectLines(Mat src) {
// TODO Auto-generated method stub
- // Detecting edges of it
+ System.out.println("识别关系");
+ // 先检测边缘。然后从边缘集中检测直线
Mat canny = new Mat();
- Imgproc.Canny(src, canny, 50, 200, 3, false);
-
- // Detecting the hough lines from (canny)
+ Imgproc.Canny(src, canny, 50, 150, 3, true);
+ // 从边缘集中检测直线
Mat lines = new Mat();
-
- Imgproc.HoughLinesP(canny, lines, 1, Math.PI / 2, 80, 80, 80);
-
- // Drawing lines on the image
- double[] data;
- double rho, theta;
- Point pt1 = new Point();
- Point pt2 = new Point();
- double a, b;
- double x0, y0;
-
+ Imgproc.HoughLinesP(canny, lines, 1, Math.PI / 4, 12, 17, 20);
+ // 将检测到的直线绘制到图中
for (int i = 0; i < lines.rows(); i++) {
- data = lines.get(i, 0);
- pt1.x = data[0];
- pt1.y = data[1];
- pt2.x = data[2];
- pt2.y = data[3];
+ Point pt1 = new Point(lines.get(i, 0)[0], lines.get(i, 0)[1]);
+ Point pt2 = new Point(lines.get(i, 0)[2], lines.get(i, 0)[3]);
Imgproc.line(src, pt1, pt2, new Scalar(187, 255, 255), 2);
}
// Writing the image
Imgcodecs.imwrite("D:\\eclipse-committers\\uml-code-trace\\src\\test\\resources\\result.png", src);
+ System.out.println("识别关系完毕,共" + lines.rows() + "条");
}
}
diff --git a/src/test/resources/result.png b/src/test/resources/result.png
index bd036f17f2d2dccb4198717adc5070adb98a5fbf..d49509128935a2a6340c1f393a42c1a3bfdd31a5 100644
Binary files a/src/test/resources/result.png and b/src/test/resources/result.png differ