|
|
@@ -1,8 +1,9 @@
|
|
|
package com.izouma.awesomeadmin.util;
|
|
|
|
|
|
import com.izouma.awesomeadmin.service.OSSFileService;
|
|
|
+import org.apache.commons.lang3.RandomStringUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.bytedeco.javacpp.indexer.UByteArrayIndexer;
|
|
|
+import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
import org.bytedeco.javacpp.indexer.UByteRawIndexer;
|
|
|
import org.bytedeco.javacpp.tesseract;
|
|
|
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
|
|
@@ -25,13 +26,13 @@ import java.util.regex.Pattern;
|
|
|
import static org.bytedeco.javacpp.lept.pixRead;
|
|
|
import static org.bytedeco.javacpp.opencv_core.*;
|
|
|
import static org.bytedeco.javacpp.opencv_imgcodecs.imencode;
|
|
|
-import static org.bytedeco.javacpp.opencv_imgcodecs.imwrite;
|
|
|
import static org.bytedeco.javacpp.opencv_imgproc.*;
|
|
|
import static org.bytedeco.javacpp.opencv_ml.SVM;
|
|
|
import static org.bytedeco.javacpp.tesseract.PSM_SINGLE_LINE;
|
|
|
|
|
|
public class VideoProcessToolNew {
|
|
|
private OSSFileService ossFileService = new OSSFileService();
|
|
|
+ public String imgPrefix = "/tmp/";
|
|
|
|
|
|
public Map<String, String> processVideo(String path, int frameSkip) throws FrameGrabber.Exception {
|
|
|
SVM svm = SVM.load(GetResource.class.getClassLoader().getResource("trainneddata/pubg.xml").getPath());
|
|
|
@@ -53,16 +54,29 @@ public class VideoProcessToolNew {
|
|
|
}
|
|
|
Mat frame = removeBlackBarAndRotate(converterToMat.convert(vFrame));
|
|
|
if (matchGameOver(svm, frame)) {
|
|
|
- String rank = extractRank(frame);
|
|
|
- if (StringUtils.isEmpty(rank)) continue;
|
|
|
- String time = extractGameTime(frame);
|
|
|
- if (StringUtils.isEmpty(time)) continue;
|
|
|
-
|
|
|
- map.put("rank", rank);
|
|
|
- map.put("time", time);
|
|
|
- map.put("image", uploadImage(frame));
|
|
|
- System.out.println(map);
|
|
|
- break;
|
|
|
+ if (map.get("rank") == null) {
|
|
|
+ String rank = extractRank(frame);
|
|
|
+ if (StringUtils.isNotEmpty(rank))
|
|
|
+ map.put("rank", rank);
|
|
|
+ }
|
|
|
+ if (map.get("total") == null) {
|
|
|
+ String total = extractTotalNum(frame);
|
|
|
+ if (StringUtils.isNotEmpty(total))
|
|
|
+ map.put("total", total);
|
|
|
+ }
|
|
|
+ if (map.get("参赛时间") == null) {
|
|
|
+ Map<String, String> statistics = getStatistics(frame);
|
|
|
+ if (statistics != null)
|
|
|
+ map.putAll(statistics);
|
|
|
+ }
|
|
|
+ if (map.get("rank") != null
|
|
|
+ && map.get("total") != null
|
|
|
+ && map.get("参赛时间") != null) {
|
|
|
+ imwrite(DateFormatUtils.format(new Date(), "yyyyMMddhhmmss") + RandomStringUtils.randomAlphabetic(4) + ".jpg", frame);
|
|
|
+ map.put("image", uploadImage(frame));
|
|
|
+ System.out.println(map);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
frame.release();
|
|
|
System.out.println(frameCount + " frame processed");
|
|
|
@@ -94,10 +108,54 @@ public class VideoProcessToolNew {
|
|
|
String result = null;
|
|
|
int m = src.rows();
|
|
|
int n = src.cols();
|
|
|
- Mat roi = new Mat(src, new Range(0, (int) (m * 0.4)), new Range((int) (n * 0.75), n));
|
|
|
- Mat filtered = rankFilter(roi);
|
|
|
+ Mat roi = new Mat(src, new Range(0, (int) (m * 0.093)), new Range((int) (n * 0.44), (int) (n * 0.56)));
|
|
|
+ imwrite("rank.jpg", roi);
|
|
|
+
|
|
|
+ Mat filtered = new Mat(roi.rows(), roi.cols(), CV_8UC1, new Scalar(0));
|
|
|
+ Mat hsvImg = new Mat();
|
|
|
+ cvtColor(roi, hsvImg, COLOR_BGR2HSV);
|
|
|
+
|
|
|
+ UByteRawIndexer hsvIndexer = hsvImg.createIndexer();
|
|
|
+ UByteRawIndexer filteredIndexer = filtered.createIndexer();
|
|
|
+ for (int i = 0; i < roi.rows(); i++) {
|
|
|
+ for (int j = 0; j < roi.cols(); j++) {
|
|
|
+ int h = hsvIndexer.get(i, j, 0);
|
|
|
+ int s = hsvIndexer.get(i, j, 1);
|
|
|
+ int v = hsvIndexer.get(i, j, 2);
|
|
|
+ int dh = 0;
|
|
|
+ if (h > 26) {
|
|
|
+ dh = h - 26;
|
|
|
+ } else if (h < 21) {
|
|
|
+ dh = 21 - h;
|
|
|
+ }
|
|
|
+ int ds = 0;
|
|
|
+ if (s > 161) {
|
|
|
+ ds = s - 161;
|
|
|
+ } else if (s < 120) {
|
|
|
+ ds = 120 - s;
|
|
|
+ }
|
|
|
+ int dv = 0;
|
|
|
+ if (v > 251) {
|
|
|
+ dv = v - 251;
|
|
|
+ } else if (v < 238) {
|
|
|
+ dv = 238 - v;
|
|
|
+ }
|
|
|
+ int gray = (int) (255 - Math.min(255, dh * 50)
|
|
|
+ - Math.min(255, ds * 3)
|
|
|
+ - Math.min(255, dv * 10));
|
|
|
+ gray = gray < 0 ? 0 : gray;
|
|
|
+ // int gray = (h == 26 && Math.abs(s - S) < 50) ? 255 : 0;
|
|
|
+ filteredIndexer.put(i, j, gray);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hsvIndexer.release();
|
|
|
+ hsvImg.release();
|
|
|
+ filteredIndexer.release();
|
|
|
+
|
|
|
+ imwrite("rank_filtered.jpg", filtered);
|
|
|
Mat gray = new Mat();
|
|
|
adaptiveThreshold(filtered, gray, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 15, 12);
|
|
|
+ imwrite("rank_gray.jpg", gray);
|
|
|
MatVector contours = new MatVector();
|
|
|
findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
|
|
|
List<Rect> rects = new ArrayList<>();
|
|
|
@@ -115,11 +173,9 @@ public class VideoProcessToolNew {
|
|
|
String str = doOCR(txtImg);
|
|
|
txtImg.release();
|
|
|
System.out.println(str);
|
|
|
- rectangle(roi, rect, new Scalar(0, 0, 255, 0), 2, LINE_AA, 0);
|
|
|
if (str != null) {
|
|
|
str = str.replaceAll("[ \n]", "");
|
|
|
if (Pattern.matches("^第\\d{1,3}$", str)) {
|
|
|
- rectangle(roi, rect, new Scalar(0, 255, 0, 0), 2, LINE_AA, 0);
|
|
|
result = str;
|
|
|
break;
|
|
|
}
|
|
|
@@ -132,20 +188,37 @@ public class VideoProcessToolNew {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- public String extractGameTime(Mat src) {
|
|
|
- Mat out = new Mat();
|
|
|
- bilateralFilter(src, out, 25, 25 * 2, 25 / 2f);
|
|
|
-
|
|
|
- imwrite("/tmp/time.jpg", out);
|
|
|
+ public String extractTotalNum(Mat src) {
|
|
|
String result = null;
|
|
|
int m = src.rows();
|
|
|
int n = src.cols();
|
|
|
- Mat roi = new Mat(out, new Range((int) (m * 0.5), (int) (m * 0.8)), new Range((int) (n * 0.5), n));
|
|
|
- Mat filtered = timeFilter(roi);
|
|
|
- imwrite("/tmp/time_filtered.jpg", filtered);
|
|
|
+ Mat roi = new Mat(src, new Range(0, (int) (m * 0.08)), new Range((int) (n * 0.42), (int) (n * 0.58)));
|
|
|
+ imwrite("total.png", roi);
|
|
|
+
|
|
|
+ Mat totalFiltered = new Mat(roi.rows(), roi.cols(), CV_8UC1, new Scalar(0));
|
|
|
+ Mat hsvImg = new Mat();
|
|
|
+ cvtColor(roi, hsvImg, COLOR_BGR2HSV);
|
|
|
+
|
|
|
+ UByteRawIndexer hsvIndexer = hsvImg.createIndexer();
|
|
|
+ UByteRawIndexer resultIndexer = totalFiltered.createIndexer();
|
|
|
+ for (int i = 0; i < roi.rows(); i++) {
|
|
|
+ for (int j = 0; j < roi.cols(); j++) {
|
|
|
+ int h = hsvIndexer.get(i, j, 0);
|
|
|
+ int s = hsvIndexer.get(i, j, 1);
|
|
|
+ int v = hsvIndexer.get(i, j, 2);
|
|
|
+
|
|
|
+ int gray = 255 - 2 * s;
|
|
|
+ gray = gray < 0 ? 0 : gray;
|
|
|
+ resultIndexer.put(i, j, gray);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hsvIndexer.release();
|
|
|
+ hsvImg.release();
|
|
|
+ resultIndexer.release();
|
|
|
+ imwrite("total_filtered.png", totalFiltered);
|
|
|
Mat gray = new Mat();
|
|
|
- adaptiveThreshold(filtered, gray, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 15, 12);
|
|
|
- imwrite("/tmp/time_gray.jpg", gray);
|
|
|
+ adaptiveThreshold(totalFiltered, gray, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 15, 12);
|
|
|
+ imwrite("rank_gray.jpg", gray);
|
|
|
MatVector contours = new MatVector();
|
|
|
findContours(gray, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
|
|
|
List<Rect> rects = new ArrayList<>();
|
|
|
@@ -159,29 +232,136 @@ public class VideoProcessToolNew {
|
|
|
for (int i = 0; i < rects.size(); i++) {
|
|
|
Rect rect = rects.get(i);
|
|
|
if (i < 5) {
|
|
|
- Mat txtImg = new Mat(filtered, new Range(rect.y(), rect.y() + rect.height()), new Range(rect.x(), rect.x() + rect.width()));
|
|
|
- resize(txtImg, txtImg, new Size(0, 0), 3, 3, INTER_LINEAR);
|
|
|
-
|
|
|
+ Mat txtImg = new Mat(totalFiltered, new Range(rect.y(), rect.y() + rect.height()), new Range(rect.x(), rect.x() + rect.width()));
|
|
|
String str = doOCR(txtImg);
|
|
|
txtImg.release();
|
|
|
- System.out.println(str);
|
|
|
- rectangle(roi, rect, new Scalar(0, 0, 255, 0), 2, LINE_AA, 0);
|
|
|
if (str != null) {
|
|
|
str = str.replaceAll("[ \n]", "");
|
|
|
- if (Pattern.matches("((^([0-9]+[.][0-9]*))|(^\\d{1,2}))分钟", str)) {
|
|
|
- rectangle(roi, rect, new Scalar(0, 255, 0, 0), 2, LINE_AA, 0);
|
|
|
- result = str;
|
|
|
+ if (Pattern.matches("^/\\d{1,3}$", str)) {
|
|
|
+ result = str.replace("/", "");
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- filtered.release();
|
|
|
+ totalFiltered.release();
|
|
|
gray.release();
|
|
|
+ System.out.println(result);
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String extractMode(Mat src) {
|
|
|
+ String result = null;
|
|
|
+ int m = src.rows();
|
|
|
+ int n = src.cols();
|
|
|
+ Mat roi = new Mat(src, new Range(0, (int) (m * 0.065)), new Range(0, (int) (n * 0.2)));
|
|
|
+ imwrite("mode.png", roi);
|
|
|
+
|
|
|
+ Mat filtered = new Mat(roi.rows(), roi.cols(), CV_8UC1, new Scalar(0));
|
|
|
+ Mat hsvImg = new Mat();
|
|
|
+ cvtColor(roi, hsvImg, COLOR_BGR2HSV);
|
|
|
+
|
|
|
+ UByteRawIndexer hsvIndexer = hsvImg.createIndexer();
|
|
|
+ UByteRawIndexer bgrIndexer = roi.createIndexer();
|
|
|
+ UByteRawIndexer resultIndexer = filtered.createIndexer();
|
|
|
+ for (int i = 0; i < roi.rows(); i++) {
|
|
|
+ for (int j = 0; j < roi.cols(); j++) {
|
|
|
+ int h = hsvIndexer.get(i, j, 0);
|
|
|
+ int s = hsvIndexer.get(i, j, 1);
|
|
|
+ int v = hsvIndexer.get(i, j, 2);
|
|
|
+ int b = bgrIndexer.get(i, j, 0);
|
|
|
+ int g = bgrIndexer.get(i, j, 1);
|
|
|
+ int r = bgrIndexer.get(i, j, 2);
|
|
|
+
|
|
|
+ int dr = Math.abs(r - 220);
|
|
|
+ int dg = Math.abs(g - 220);
|
|
|
+ int db = Math.abs(b - 220);
|
|
|
+
|
|
|
+ int dbgr = Math.abs(b - g) + Math.abs(b - r) + Math.abs(r - g);
|
|
|
+
|
|
|
+ int gray = (int) (255 - Math.pow(dr, 2) * 0.015 - Math.pow(dg, 2) * 0.015 - Math.pow(db, 2) * 0.015 - Math.pow(dbgr, 2) * 0.015);
|
|
|
+ // gray = (int) (gray / 128f * 255);
|
|
|
+ // gray = 255 - Math.abs(gray - 200) * 2;
|
|
|
+ if (gray > 220) {
|
|
|
+ gray = 0;
|
|
|
+ } else if (gray > 190) {
|
|
|
+ gray = 220 - 190;
|
|
|
+ } else {
|
|
|
+ gray = 255;
|
|
|
+ }
|
|
|
+ resultIndexer.put(i, j, gray);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ hsvIndexer.release();
|
|
|
+ bgrIndexer.release();
|
|
|
+ hsvImg.release();
|
|
|
+ resultIndexer.release();
|
|
|
+ imwrite("mode_filtered.png", filtered);
|
|
|
+ result = doOCR(filtered, "chi_sim");
|
|
|
+ if (StringUtils.isNotEmpty(result)) {
|
|
|
+ result = result.replace(" ", "").replace("\n", "");
|
|
|
+ }
|
|
|
+ System.out.println(result);
|
|
|
+ filtered.release();
|
|
|
roi.release();
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ public Map<String, String> getStatistics(Mat src) {
|
|
|
+ imwrite("time.jpg", src);
|
|
|
+ int m = src.rows();
|
|
|
+ int n = src.cols();
|
|
|
+ Mat roi = new Mat(src, new Range((int) (m * 0.569), (int) (m * 0.625)), new Range((int) (n * 0.3), (int) (n * 0.8)));
|
|
|
+ Mat filtered = timeFilter(roi);
|
|
|
+ imwrite("time_filtered.jpg", filtered);
|
|
|
+
|
|
|
+ Map<String, String> map = new HashMap<>();
|
|
|
+ Rect[] rects = {
|
|
|
+ new Rect(0, 0, (int) (filtered.cols() * 0.128), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.128), 0, (int) (filtered.cols() * 0.128), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.256), 0, (int) (filtered.cols() * 0.162), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.428), 0, (int) (filtered.cols() * 0.114), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.542), 0, (int) (filtered.cols() * 0.1), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.642), 0, (int) (filtered.cols() * 0.1), filtered.rows()),
|
|
|
+ new Rect((int) (filtered.cols() * 0.742), 0, (int) (filtered.cols() * 0.1), filtered.rows())
|
|
|
+ };
|
|
|
+ String[] names = {"淘汰", "伤害", "参赛时间", "治疗量", "救援", "助攻", "评分"};
|
|
|
+ int i = 0;
|
|
|
+ for (Rect rect : rects) {
|
|
|
+ Mat txtImg = new Mat(filtered, new Range(rect.y(), rect.y() + rect.height()), new Range(rect.x(), rect.x() + rect.width()));
|
|
|
+
|
|
|
+ Rect rect1 = boundingRect(txtImg);
|
|
|
+ int y1 = rect1.y() - 5;
|
|
|
+ y1 = y1 < 0 ? 0 : y1;
|
|
|
+ int y2 = rect1.y() + rect1.height() + 5;
|
|
|
+ y2 = y2 > (txtImg.rows() - 1) ? (txtImg.rows() - 1) : y2;
|
|
|
+ int x1 = rect1.x() - 5;
|
|
|
+ x1 = x1 < 0 ? 0 : x1;
|
|
|
+ int x2 = rect1.x() + rect1.width() + 5;
|
|
|
+ x2 = x2 > (txtImg.cols() - 1) ? (txtImg.cols() - 1) : x2;
|
|
|
+ txtImg = txtImg.rowRange(y1, y2).colRange(x1, x2);
|
|
|
+ bitwise_not(txtImg, txtImg);
|
|
|
+ resize(txtImg, txtImg, new Size(0, 0), 3, 3, INTER_LINEAR);
|
|
|
+ String str = doOCR(txtImg);
|
|
|
+ if (StringUtils.isNotEmpty(str)) {
|
|
|
+ str = str.replaceAll("[ \n]", "");
|
|
|
+ }
|
|
|
+ map.put(names[i], str);
|
|
|
+ System.out.println(names[i] + str);
|
|
|
+ imwrite(names[i] + ".png", txtImg);
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+
|
|
|
+ filtered.release();
|
|
|
+ roi.release();
|
|
|
+ if (map.get("参赛时间") != null) {
|
|
|
+ if (Pattern.matches("((^([0-9]+[.][0-9]*))|(^\\d{1,2}))分钟", map.get("参赛时间")))
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
public Mat bgrFilter(Mat src, int b, int g, int r) {
|
|
|
Mat result = new Mat(src.rows(), src.cols(), CV_8UC1, new Scalar(0));
|
|
|
UByteRawIndexer srcIndexer = src.createIndexer();
|
|
|
@@ -206,19 +386,63 @@ public class VideoProcessToolNew {
|
|
|
}
|
|
|
|
|
|
public Mat rankFilter(Mat src) {
|
|
|
- return bgrFilter(src, 12, 243, 252);
|
|
|
+ Mat result = new Mat(src.rows(), src.cols(), CV_8UC1, new Scalar(0));
|
|
|
+ Mat hsvImg = new Mat();
|
|
|
+ cvtColor(src, hsvImg, COLOR_BGR2HSV);
|
|
|
+
|
|
|
+ UByteRawIndexer hsvIndexer = hsvImg.createIndexer();
|
|
|
+ UByteRawIndexer resultIndexer = result.createIndexer();
|
|
|
+ for (int i = 0; i < src.rows(); i++) {
|
|
|
+ for (int j = 0; j < src.cols(); j++) {
|
|
|
+ int h = hsvIndexer.get(i, j, 0);
|
|
|
+ int s = hsvIndexer.get(i, j, 1);
|
|
|
+ int v = hsvIndexer.get(i, j, 2);
|
|
|
+ int dh = 0;
|
|
|
+ if (h > 26) {
|
|
|
+ dh = h - 26;
|
|
|
+ } else if (h < 21) {
|
|
|
+ dh = 21 - h;
|
|
|
+ }
|
|
|
+ int ds = 0;
|
|
|
+ if (s > 161) {
|
|
|
+ ds = s - 161;
|
|
|
+ } else if (s < 120) {
|
|
|
+ ds = 120 - s;
|
|
|
+ }
|
|
|
+ int dv = 0;
|
|
|
+ if (v > 251) {
|
|
|
+ dv = v - 251;
|
|
|
+ } else if (v < 238) {
|
|
|
+ dv = 238 - v;
|
|
|
+ }
|
|
|
+ int gray = (int) (255 - Math.min(255, dh * 50)
|
|
|
+ - Math.min(255, ds * 3)
|
|
|
+ - Math.min(255, dv * 10));
|
|
|
+ gray = gray < 0 ? 0 : gray;
|
|
|
+ // int gray = (h == 26 && Math.abs(s - S) < 50) ? 255 : 0;
|
|
|
+ resultIndexer.put(i, j, gray);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ hsvIndexer.release();
|
|
|
+ hsvImg.release();
|
|
|
+ resultIndexer.release();
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
public Mat timeFilter(Mat src) {
|
|
|
- return bgrFilter(src, 40, 183, 210);
|
|
|
+ return bgrFilter(src, 27, 129, 243);
|
|
|
}
|
|
|
|
|
|
private String doOCR(Mat img) {
|
|
|
- imwrite("/tmp/text.jpg", img);
|
|
|
+ return doOCR(img, "pubg");
|
|
|
+ }
|
|
|
+
|
|
|
+ private String doOCR(Mat img, String lang) {
|
|
|
+ imwrite("text.jpg", img);
|
|
|
final tesseract.TessBaseAPI baseApi = new tesseract.TessBaseAPI();
|
|
|
- baseApi.Init(GetResource.class.getClassLoader().getResource("trainneddata").getPath(), "pubg");
|
|
|
+ baseApi.Init(GetResource.class.getClassLoader().getResource("trainneddata").getPath(), lang);
|
|
|
baseApi.SetPageSegMode(PSM_SINGLE_LINE);
|
|
|
- baseApi.SetImage(pixRead("/tmp/text.jpg"));
|
|
|
+ baseApi.SetImage(pixRead(imgPrefix + "text.jpg"));
|
|
|
String recognizedText = baseApi.GetUTF8Text().getString();
|
|
|
return recognizedText;
|
|
|
}
|
|
|
@@ -265,4 +489,8 @@ public class VideoProcessToolNew {
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
+
|
|
|
+ private void imwrite(String name, Mat img) {
|
|
|
+ org.bytedeco.javacpp.opencv_imgcodecs.imwrite(imgPrefix + name, img);
|
|
|
+ }
|
|
|
}
|