|
|
@@ -1,323 +0,0 @@
|
|
|
-package com.izouma.awesomeadmin.util;
|
|
|
-
|
|
|
-import com.izouma.awesomeadmin.service.OSSFileService;
|
|
|
-import io.netty.buffer.ByteBuf;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.bytedeco.javacpp.indexer.UByteRawIndexer;
|
|
|
-import org.bytedeco.javacpp.lept;
|
|
|
-import org.bytedeco.javacpp.opencv_imgproc;
|
|
|
-import org.bytedeco.javacpp.opencv_ml;
|
|
|
-import org.bytedeco.javacpp.tesseract;
|
|
|
-import org.bytedeco.javacv.*;
|
|
|
-import org.hibernate.validator.internal.util.privilegedactions.GetResource;
|
|
|
-
|
|
|
-import javax.imageio.ImageIO;
|
|
|
-import java.awt.image.BufferedImage;
|
|
|
-import java.io.ByteArrayInputStream;
|
|
|
-import java.io.ByteArrayOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.nio.ByteBuffer;
|
|
|
-import java.text.SimpleDateFormat;
|
|
|
-import java.util.*;
|
|
|
-import java.util.regex.Pattern;
|
|
|
-
|
|
|
-import static org.bytedeco.javacpp.lept.pixRead;
|
|
|
-import static org.bytedeco.javacpp.lept.pixReadMem;
|
|
|
-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 VideoProcessTool {
|
|
|
- private OSSFileService ossFileService = new OSSFileService();
|
|
|
-
|
|
|
- public Map<String, String> processVideo(String path, int frameSkip) throws FrameGrabber.Exception {
|
|
|
- SVM svm = opencv_ml.SVM.load(GetResource.class.getClassLoader().getResource("trainneddata/pubg.xml").getPath());
|
|
|
- Map<String, String> map = new HashMap<>();
|
|
|
- OpenCVFrameConverter.ToMat converterToMat = new OpenCVFrameConverter.ToMat();
|
|
|
- long frameCount = 0;
|
|
|
- FrameGrabber videoGrabber = new FFmpegFrameGrabber(path);
|
|
|
- videoGrabber.start();
|
|
|
- Frame vFrame;
|
|
|
- do {
|
|
|
- vFrame = videoGrabber.grabFrame();
|
|
|
- if (vFrame != null) {
|
|
|
- frameCount++;
|
|
|
- if (frameCount % 200 == 0) {
|
|
|
- System.gc();
|
|
|
- }
|
|
|
- if (frameSkip > 0 && frameCount % frameSkip != 0) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- Mat frame = converterToMat.convert(vFrame);
|
|
|
- if (matchGameOver(svm, frame)) {
|
|
|
- String rank = extractRank(frame);
|
|
|
- String time = extractGameTime(frame);
|
|
|
- if (StringUtils.isEmpty(rank) || StringUtils.isEmpty(time)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- rank = rank.trim().replace(" ", "").replace("\n", "");
|
|
|
- time = time.trim().replace(" ", "").replace("\n", "");
|
|
|
- if (!Pattern.matches("^第\\d{1,3}$", rank)
|
|
|
- || !Pattern.matches("((^([0-9]+[.][0-9]*))|(^\\d{1,2}))分钟", time)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- map.put("rank", rank);
|
|
|
- map.put("time", time);
|
|
|
- map.put("image", uploadImage(frame));
|
|
|
- System.out.println(map);
|
|
|
- break;
|
|
|
- }
|
|
|
- frame.release();
|
|
|
- System.out.println(frameCount + " frame processed");
|
|
|
- }
|
|
|
- } while (vFrame != null);
|
|
|
- videoGrabber.stop();
|
|
|
- videoGrabber.release();
|
|
|
- svm.deallocate();
|
|
|
- System.gc();
|
|
|
- return map;
|
|
|
- }
|
|
|
-
|
|
|
- public boolean matchGameOver(opencv_ml.SVM svm, Mat inputImage) {
|
|
|
- Mat rotated = new Mat();
|
|
|
- if (inputImage.cols() < inputImage.rows()) {
|
|
|
- rotate(inputImage, rotated, ROTATE_90_COUNTERCLOCKWISE);
|
|
|
- } else {
|
|
|
- inputImage.copyTo(rotated);
|
|
|
- }
|
|
|
- Mat resized = new Mat();
|
|
|
- removeBlackBar(rotated);
|
|
|
- resize(rotated, resized, new Size(854, 480));
|
|
|
- Mat reshaped = resized.reshape(1, 1);
|
|
|
- Mat toPredict = new Mat();
|
|
|
- reshaped.convertTo(toPredict, CV_32F);
|
|
|
- float res = svm.predict(toPredict);
|
|
|
-
|
|
|
- rotated.release();
|
|
|
- resized.release();
|
|
|
- reshaped.release();
|
|
|
- toPredict.release();
|
|
|
- return res == 1;
|
|
|
- }
|
|
|
-
|
|
|
- public String extractRank(Mat inputImage) {
|
|
|
- String result = null;
|
|
|
- int m = inputImage.rows();
|
|
|
- int n = inputImage.cols();
|
|
|
- Mat roi = inputImage.rowRange(0, (int) (m * 0.4)).colRange((int) (n * 0.75), n);
|
|
|
-
|
|
|
- Mat resultGray = new Mat(roi.rows(), roi.cols(), CV_8U, new Scalar(0));
|
|
|
- HSVFilter(roi, resultGray, 25, 65, 40, 255, 130, 255);
|
|
|
-
|
|
|
- Mat eroded = new Mat();
|
|
|
- int erosion_size = m / 400;
|
|
|
- erode(resultGray, eroded, erosion_size);
|
|
|
- resultGray.release();
|
|
|
-
|
|
|
- Mat dilated = new Mat();
|
|
|
- int dilation_size = m / 400 * 4;
|
|
|
- dilate(eroded, dilated, dilation_size);
|
|
|
-
|
|
|
- MatVector contours = new MatVector();
|
|
|
- Mat hierarchy = new Mat();
|
|
|
- findContours(dilated, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
|
|
|
- eroded.release();
|
|
|
- dilated.release();
|
|
|
- hierarchy.release();
|
|
|
-
|
|
|
- Rect textRect = new Rect();
|
|
|
- for (int i = 0; i < contours.size(); i++) {
|
|
|
- Rect rect = boundingRect(contours.get(i));
|
|
|
- if (rect.area() > textRect.area()) {
|
|
|
- textRect = rect;
|
|
|
- }
|
|
|
- }
|
|
|
- if (textRect.width() > 0 && textRect.height() > 0) {
|
|
|
- Mat text = roi.rowRange(textRect.y(), textRect.y() + textRect.height()).colRange(textRect.x(), textRect.x() + textRect.width());
|
|
|
- Mat textBin = new Mat(text.rows(), text.cols(), CV_8UC1);
|
|
|
- UByteRawIndexer textIndexer = text.createIndexer();
|
|
|
- UByteRawIndexer textBinIndexer = textBin.createIndexer();
|
|
|
- for (int i = 0; i < text.rows(); i++) {
|
|
|
- for (int j = 0; j < text.cols(); j++) {
|
|
|
- int s = (textIndexer.get(i, j, 1) + textIndexer.get(i, j, 2)) / 2;
|
|
|
- textBinIndexer.put(i, j, s > 220 ? s : 0);
|
|
|
- }
|
|
|
- }
|
|
|
- textIndexer.release();
|
|
|
- textBinIndexer.release();
|
|
|
- text.release();
|
|
|
- Mat blurred = new Mat();
|
|
|
- medianBlur(textBin, blurred, 3);
|
|
|
- textBin.release();
|
|
|
-
|
|
|
- for (int i = 0; i < contours.size(); i++) {
|
|
|
- Rect rect = boundingRect(contours.get(i));
|
|
|
- rectangle(roi, rect, new Scalar(0, 0, 255, 0), 2, LINE_AA, 0);
|
|
|
- }
|
|
|
- rectangle(roi, textRect, new Scalar(0, 255, 0, 0), 2, LINE_AA, 0);
|
|
|
- result = doOCR(blurred);
|
|
|
- imwrite("/Users/drew/Desktop/img/text.jpg", blurred);
|
|
|
- blurred.release();
|
|
|
- }
|
|
|
- roi.release();
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- public String extractGameTime(Mat inputImage) {
|
|
|
- String result = null;
|
|
|
- int m = inputImage.rows();
|
|
|
- int n = inputImage.cols();
|
|
|
- inputImage = inputImage.rowRange((int) (m * 0.5), (int) (m * 0.8)).colRange((int) (n * 0.5), n);
|
|
|
- Mat resultGray = new Mat(inputImage.rows(), inputImage.cols(), CV_8U, new Scalar(0));
|
|
|
- HSVFilter(inputImage, resultGray, 15, 28, 80, 255, 80, 255);
|
|
|
-
|
|
|
- Mat dilate1 = new Mat();
|
|
|
- int dilation_size = resultGray.rows() / 120 * 3;
|
|
|
- dilate(resultGray, dilate1, dilation_size);
|
|
|
-
|
|
|
- Mat erode = new Mat();
|
|
|
- int erosion_size = resultGray.rows() / 120 * 3;
|
|
|
- erode(dilate1, erode, erosion_size);
|
|
|
-
|
|
|
- Mat dilate2 = new Mat();
|
|
|
- dilate(erode, dilate2, dilation_size);
|
|
|
-
|
|
|
- dilate1.release();
|
|
|
- erode.release();
|
|
|
- resultGray.release();
|
|
|
- resultGray = new Mat();
|
|
|
- dilate2.copyTo(resultGray);
|
|
|
- dilate2.release();
|
|
|
-
|
|
|
- MatVector contours = new MatVector();
|
|
|
- Mat hierarchy = new Mat();
|
|
|
- findContours(resultGray, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);
|
|
|
- hierarchy.release();
|
|
|
- Rect textRect = new Rect();
|
|
|
- for (int i = 0; i < contours.size(); i++) {
|
|
|
- Rect rect = boundingRect(contours.get(i));
|
|
|
- if (rect.area() > textRect.area() && rect.height() < inputImage.rows() / 3) {
|
|
|
- textRect = rect;
|
|
|
- }
|
|
|
- }
|
|
|
- if (textRect.width() > 0 && textRect.height() > 0) {
|
|
|
- Mat roi = inputImage.rowRange(textRect.y(), textRect.y() + textRect.height()).colRange(textRect.x(), textRect.x() + textRect.width());
|
|
|
- Mat textImg = new Mat();
|
|
|
- roi.convertTo(textImg, CV_8UC3);
|
|
|
- roi.release();
|
|
|
- cvtColor(textImg, textImg, COLOR_BGR2GRAY);
|
|
|
- Mat textGray = new Mat();
|
|
|
- textImg.convertTo(textGray, CV_8UC1);
|
|
|
- imwrite("/Users/drew/Desktop/text.jpg", textImg);
|
|
|
- textImg.release();
|
|
|
- for (int i = 0; i < contours.size(); i++) {
|
|
|
- Rect rect = boundingRect(contours.get(i));
|
|
|
- rectangle(inputImage, rect, new Scalar(0, 0, 255, 0), 2, LINE_AA, 0);
|
|
|
- }
|
|
|
- rectangle(inputImage, textRect, new Scalar(0, 255, 0, 0), 2, LINE_AA, 0);
|
|
|
- result = doOCR(textGray);
|
|
|
- textGray.release();
|
|
|
- }
|
|
|
- resultGray.release();
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private void dilate(Mat src, Mat dst, int dilation_size) {
|
|
|
- Mat dilationElement = getStructuringElement(MORPH_ELLIPSE,
|
|
|
- new Size(2 * dilation_size + 1, 2 * dilation_size + 1),
|
|
|
- new Point(dilation_size, dilation_size));
|
|
|
- opencv_imgproc.dilate(src, dst, dilationElement);
|
|
|
- dilationElement.release();
|
|
|
- }
|
|
|
-
|
|
|
- private void erode(Mat src, Mat dst, int erosion_size) {
|
|
|
- Mat erodeElement = getStructuringElement(MORPH_RECT,
|
|
|
- new Size(2 * erosion_size + 1, 2 * erosion_size + 1),
|
|
|
- new Point(erosion_size, erosion_size));
|
|
|
- opencv_imgproc.erode(src, dst, erodeElement);
|
|
|
- erodeElement.release();
|
|
|
- }
|
|
|
-
|
|
|
- private void HSVFilter(Mat inputImage, Mat resultGray, int h_min, int h_max, int s_min, int s_max, int v_min, int v_max) {
|
|
|
- Mat hsvImage = new Mat();
|
|
|
- Mat blurred = new Mat();
|
|
|
- blur(inputImage, blurred, new Size(3, 3));
|
|
|
- cvtColor(blurred, hsvImage, COLOR_BGR2HSV);
|
|
|
- double H, S, V;
|
|
|
- UByteRawIndexer hsvIndexer = hsvImage.createIndexer();
|
|
|
- UByteRawIndexer resultGrayIndexer = resultGray.createIndexer();
|
|
|
- for (int i = 0; i < hsvImage.rows(); i++) {
|
|
|
- for (int j = 0; j < hsvImage.cols(); j++) {
|
|
|
- H = hsvIndexer.get(i, j, 0);
|
|
|
- S = hsvIndexer.get(i, j, 1);
|
|
|
- V = hsvIndexer.get(i, j, 2);
|
|
|
-
|
|
|
- if ((H >= h_min && H <= h_max)
|
|
|
- && (S >= s_min && S <= s_max)
|
|
|
- && (V >= v_min && V <= v_max)) {
|
|
|
- resultGrayIndexer.put(i, j, 255);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- imwrite("/Users/drew/Desktop/img/text0.jpg", resultGray);
|
|
|
- hsvImage.release();
|
|
|
- blurred.release();
|
|
|
- hsvIndexer.release();
|
|
|
- resultGrayIndexer.release();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- private String doOCR(Mat img) {
|
|
|
- imwrite("/tmp/text.jpg", img);
|
|
|
- final tesseract.TessBaseAPI baseApi = new tesseract.TessBaseAPI();
|
|
|
- baseApi.Init(GetResource.class.getClassLoader().getResource("trainneddata").getPath(), "pubg");
|
|
|
- baseApi.SetPageSegMode(PSM_SINGLE_LINE);
|
|
|
- baseApi.SetImage(pixRead("/tmp/text.jpg"));
|
|
|
- String recognizedText = baseApi.GetUTF8Text().getString();
|
|
|
- return recognizedText;
|
|
|
- }
|
|
|
-
|
|
|
- private void removeBlackBar(Mat src) {
|
|
|
- Mat gray = new Mat();
|
|
|
- cvtColor(src, gray, COLOR_BGR2GRAY);
|
|
|
- threshold(gray, gray, 2, 255, THRESH_BINARY);
|
|
|
- Rect rect = boundingRect(gray);
|
|
|
- src.colRange(rect.x(), rect.x() + rect.width()).rowRange(rect.y(), rect.y() + rect.height());
|
|
|
- gray.release();
|
|
|
- rect.deallocate();
|
|
|
- }
|
|
|
-
|
|
|
- public BufferedImage createBufferedImage(Mat mat) {
|
|
|
- ByteBuffer byteBuffer = ByteBuffer.allocate(mat.cols() * mat.rows());
|
|
|
- imencode(".jpg", mat, byteBuffer);
|
|
|
- byte ba[] = byteBuffer.array();
|
|
|
- BufferedImage bi = null;
|
|
|
- try {
|
|
|
- bi = ImageIO.read(new ByteArrayInputStream(ba));
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- return bi;
|
|
|
- }
|
|
|
-
|
|
|
- public String uploadImage(Mat frame) {
|
|
|
- try {
|
|
|
- BufferedImage image = createBufferedImage(frame);
|
|
|
- ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
|
|
|
- ImageIO.write(image, "png", baos);//写入流中
|
|
|
- byte[] bytes = baos.toByteArray();//转换成字节
|
|
|
- InputStream in = new ByteArrayInputStream(bytes);
|
|
|
- String path = String.format("images/%s-%s.jpg", new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss").format(new Date()), UUID.randomUUID().toString());
|
|
|
- return ossFileService.upload(in, path);
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|