|
|
@@ -11,6 +11,7 @@ import org.apache.commons.lang.StringUtils;
|
|
|
import org.hibernate.validator.internal.util.privilegedactions.GetResource;
|
|
|
import org.opencv.core.*;
|
|
|
import org.opencv.highgui.HighGui;
|
|
|
+import org.opencv.imgcodecs.Imgcodecs;
|
|
|
import org.opencv.imgproc.Imgproc;
|
|
|
import org.opencv.ml.SVM;
|
|
|
import org.opencv.videoio.VideoCapture;
|
|
|
@@ -23,10 +24,7 @@ import java.awt.image.BufferedImage;
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.io.IOException;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.concurrent.LinkedBlockingQueue;
|
|
|
import java.util.concurrent.ThreadPoolExecutor;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
@@ -41,10 +39,10 @@ import static org.opencv.imgproc.Imgproc.*;
|
|
|
|
|
|
@Service
|
|
|
public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
- public static boolean DEBUG = false;
|
|
|
- private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
|
|
|
- private Map<String, Map<String, Object>> resultMap = new HashMap<>();
|
|
|
- private Map<String, Long> lastStat = new HashMap<>();
|
|
|
+ public static boolean DEBUG = false;
|
|
|
+ private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
|
|
|
+ private Map<String, Map<String, Object>> resultMap = new HashMap<>();
|
|
|
+ private Map<String, Long> lastStat = new HashMap<>();
|
|
|
|
|
|
static {
|
|
|
CLibrary.INSTANCE.setlocale(CLibrary.LC_ALL, "C");
|
|
|
@@ -58,9 +56,9 @@ public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
public interface CLibrary extends Library {
|
|
|
CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
|
|
|
|
|
|
- int LC_CTYPE = 0;
|
|
|
+ int LC_CTYPE = 0;
|
|
|
int LC_NUMERIC = 1;
|
|
|
- int LC_ALL = 6;
|
|
|
+ int LC_ALL = 6;
|
|
|
|
|
|
// char *setlocale(int category, const char *locale);
|
|
|
String setlocale(int category, String locale);
|
|
|
@@ -87,20 +85,7 @@ public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
if (frameCount % 3 != 0) {
|
|
|
continue;
|
|
|
}
|
|
|
- long lastTs = lastStat.get(videoPath);
|
|
|
- if (System.currentTimeMillis() - lastTs > 60 * 1000) {
|
|
|
- break;
|
|
|
- }
|
|
|
- if (frame.cols() < frame.rows()) {
|
|
|
- rotate(frame, frame, ROTATE_90_COUNTERCLOCKWISE);
|
|
|
- }
|
|
|
- resize(frame, v, new Size(854, 480));
|
|
|
- Mat p = v.reshape(1, 1);
|
|
|
- p.convertTo(p, CV_32FC1);
|
|
|
- float res = svm.predict(p);
|
|
|
- System.out.println("predict res: " + res);
|
|
|
-
|
|
|
- if (res == 1) {
|
|
|
+ if (matchGameOver(svm, frame)) {
|
|
|
String rank = extractRank(frame);
|
|
|
String time = extractGameTime(frame);
|
|
|
if (StringUtils.isNotEmpty(rank) && StringUtils.isNotEmpty(time)) {
|
|
|
@@ -142,6 +127,20 @@ public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public boolean matchGameOver(SVM svm, Mat inputImage) {
|
|
|
+ if (inputImage.cols() < inputImage.rows()) {
|
|
|
+ rotate(inputImage, inputImage, ROTATE_90_COUNTERCLOCKWISE);
|
|
|
+ }
|
|
|
+ Mat v = new Mat();
|
|
|
+ removeBlackBar(inputImage, inputImage);
|
|
|
+ resize(inputImage, v, new Size(854, 480));
|
|
|
+ Mat p = v.reshape(1, 1);
|
|
|
+ p.convertTo(p, CV_32FC1);
|
|
|
+ float res = svm.predict(p);
|
|
|
+ return res == 1;
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public String extractRank(Mat inputImage) {
|
|
|
String result = null;
|
|
|
@@ -279,6 +278,7 @@ public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
@Override
|
|
|
public Map<String, Object> stat(String videoPath) {
|
|
|
lastStat.put(videoPath, System.currentTimeMillis());
|
|
|
@@ -361,4 +361,62 @@ public class VideoRecognitionServiceImpl implements VideoRecognitionService {
|
|
|
HighGui.imshow(name, copy);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private void removeBlackBar(Mat src, Mat dst) {
|
|
|
+ int[] top = new int[20];
|
|
|
+ int[] bottom = new int[20];
|
|
|
+ int[] left = new int[20];
|
|
|
+ int[] right = new int[20];
|
|
|
+ int rowStep = (int) (src.rows() * 0.4 / 20);
|
|
|
+ int colStep = (int) (src.cols() * 0.4 / 20);
|
|
|
+ int r = (int) (src.rows() * 0.3);
|
|
|
+ for (int i = 0; i < 20; i++) {
|
|
|
+ for (int c = 2; c + 2 < src.cols(); c++) {
|
|
|
+ double B = (src.get(r, c - 2)[0] + src.get(r, c - 1)[0] + src.get(r, c)[0] + src.get(r, c + 1)[0] + src.get(r, c + 2)[0]) / 3f;
|
|
|
+ double G = (src.get(r, c - 2)[1] + src.get(r, c - 1)[1] + src.get(r, c)[1] + src.get(r, c + 1)[1] + src.get(r, c + 2)[1]) / 3f;
|
|
|
+ double R = (src.get(r, c - 2)[2] + src.get(r, c - 1)[2] + src.get(r, c)[2] + src.get(r, c + 1)[2] + src.get(r, c + 2)[2]) / 3f;
|
|
|
+ if (B > 5 && G > 5 && R > 5) {
|
|
|
+ left[i] = c;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int c = src.cols() - 3; c - 2 >= 0; c--) {
|
|
|
+ double B = (src.get(r, c - 2)[0] + src.get(r, c - 1)[0] + src.get(r, c)[0] + src.get(r, c + 1)[0] + src.get(r, c + 2)[0]) / 3f;
|
|
|
+ double G = (src.get(r, c - 2)[1] + src.get(r, c - 1)[1] + src.get(r, c)[1] + src.get(r, c + 1)[1] + src.get(r, c + 2)[1]) / 3f;
|
|
|
+ double R = (src.get(r, c - 2)[2] + src.get(r, c - 1)[2] + src.get(r, c)[2] + src.get(r, c + 1)[2] + src.get(r, c + 2)[2]) / 3f;
|
|
|
+ if (B > 5 && G > 5 && R > 5) {
|
|
|
+ right[i] = c;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ r += rowStep;
|
|
|
+ }
|
|
|
+ int c = (int) (src.cols() * 0.3);
|
|
|
+ for (int i = 0; i < 20; i++) {
|
|
|
+ for (r = 2; r + 2 < src.rows(); r++) {
|
|
|
+ double B = (src.get(r, c - 2)[0] + src.get(r, c - 1)[0] + src.get(r, c)[0] + src.get(r, c + 1)[0] + src.get(r, c + 2)[0]) / 3f;
|
|
|
+ double G = (src.get(r, c - 2)[1] + src.get(r, c - 1)[1] + src.get(r, c)[1] + src.get(r, c + 1)[1] + src.get(r, c + 2)[1]) / 3f;
|
|
|
+ double R = (src.get(r, c - 2)[2] + src.get(r, c - 1)[2] + src.get(r, c)[2] + src.get(r, c + 1)[2] + src.get(r, c + 2)[2]) / 3f;
|
|
|
+ if (B > 5 && G > 5 && R > 5) {
|
|
|
+ top[i] = r;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (r = src.rows() - 3; r - 2 >= 0; r--) {
|
|
|
+ double B = (src.get(r, c - 2)[0] + src.get(r, c - 1)[0] + src.get(r, c)[0] + src.get(r, c + 1)[0] + src.get(r, c + 2)[0]) / 3f;
|
|
|
+ double G = (src.get(r, c - 2)[1] + src.get(r, c - 1)[1] + src.get(r, c)[1] + src.get(r, c + 1)[1] + src.get(r, c + 2)[1]) / 3f;
|
|
|
+ double R = (src.get(r, c - 2)[2] + src.get(r, c - 1)[2] + src.get(r, c)[2] + src.get(r, c + 1)[2] + src.get(r, c + 2)[2]) / 3f;
|
|
|
+ if (B > 5 && G > 5 && R > 5) {
|
|
|
+ bottom[i] = r;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ c += colStep;
|
|
|
+ }
|
|
|
+ int offsetTop = (int) Math.max(Arrays.stream(top).average().getAsDouble() - 2, 0);
|
|
|
+ int offsetBottom = (int) Math.min(Arrays.stream(bottom).average().getAsDouble() + 2, src.rows() - 1);
|
|
|
+ int offsetLeft = (int) Math.max(Arrays.stream(left).average().getAsDouble() - 2, 0);
|
|
|
+ int offsetRight = (int) Math.min(Arrays.stream(right).average().getAsDouble() + 2, src.cols() - 1);
|
|
|
+ new Mat(src, new Rect(new Point(offsetLeft, offsetTop), new Point(offsetRight, offsetBottom))).copyTo(dst);
|
|
|
+ }
|
|
|
}
|