Browse Source

图像单通道拆解

syh 5 years ago
parent
commit
d0a2d9c750

+ 82 - 21
jeecg-boot-module-system/src/main/java/org/jeecg/modules/demo/opencv/CornerCheck.java

@@ -19,8 +19,8 @@ public class CornerCheck {
     private static int EXPAND_SIZE = 3;
     public static void main(String[] args) {
 //        harris();
-//        detectConers();
-        channelSplit();
+        detectConers();
+//        channelSplit();
     }
 
     public static void channelSplit() {
@@ -45,13 +45,27 @@ public class CornerCheck {
         Map<String, Object> result = new HashMap<>();
         try {
             System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
-
-            final int maxCorners = 50, blockSize = 3;
-            final double qualityLevel = 0.01, minDistance = 20.0, k = 0.04;
+            Mat src = Imgcodecs.imread("D:\\data\\images\\163.jpg");
+            if (src.empty()) {
+                throw new Exception("no file");
+            }
+            for (int i = 0; i < src.cols(); i++) {
+                for (int j = 0; j < src.rows(); j++) {
+                    if (i > 160 && i < 470 && j > 250 && j < 750) {
+                        Imgproc.circle(src, new Point(i, j), 1, new Scalar(0, 236, 2), Imgproc.FILLED);
+                    }
+                }
+            }
+            final int maxCorners = 100, blockSize = 5;
+            final double qualityLevel = 0.04, minDistance = 20.0, k = 0.04;
             final boolean useHarrisDetector = false;
             MatOfPoint corners = new MatOfPoint();
-
-            Mat src = Imgcodecs.imread("D:\\data\\235.jpg");
+            //卷积
+            Mat kernel = new Mat(3, 3, CvType.CV_16SC1);
+            kernel.put(0, 0, 0, -1, 0, -1, 5, -1, 0, -1, 0);
+            Imgproc.filter2D(src, src, src.depth(), kernel);
+            //降噪
+            Imgproc.GaussianBlur(src, src, new Size(3, 3), 0, 0, 1);
             if (src.empty()) {
                 throw new Exception("no file");
             }
@@ -60,12 +74,26 @@ public class CornerCheck {
             //灰度
             Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGB2GRAY);
             Imgcodecs.imwrite("D:\\data\\gray.jpg", gray);
-            Mat binary = new Mat();
-            //二值化
-            Imgproc.threshold(gray, binary, 1, 255, Imgproc.THRESH_TOZERO);
-            Imgcodecs.imwrite("D:\\data\\binary.jpg", binary);
-            Imgproc.goodFeaturesToTrack(binary, corners, maxCorners, qualityLevel, minDistance,
-                    new Mat(), blockSize, useHarrisDetector, k);
+            //归一处理
+//            Core.normalize(gray,gray);
+            //Sobel算子
+            Mat grad_x = new Mat(), grad_y = new Mat();
+            Mat abs_grad_x = new Mat(), abs_grad_y = new Mat();
+            int scale = 1;
+            int delta = 0;
+            //Gradient X
+            Imgproc.Sobel(gray, grad_x, CvType.CV_16S, 1, 0, 3, scale, delta, 1);
+            //Gradient y
+            Imgproc.Sobel(gray, grad_y, CvType.CV_16S, 0, 1, 3, scale, delta, 1);
+
+            Core.convertScaleAbs(grad_x, abs_grad_x);
+            Core.convertScaleAbs(grad_y, abs_grad_y);
+
+            /// Total Gradient (approximate)
+            Mat grad = new Mat();
+            Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
+            Imgcodecs.imwrite("D:\\data\\shark.jpg", grad);
+            Imgproc.goodFeaturesToTrack(grad, corners, maxCorners, qualityLevel, minDistance, new Mat(new Size(grad.width(), grad.height()), CvType.CV_8UC1), blockSize, useHarrisDetector, k);
             Point[] pCorners = corners.toArray();
             List<Point> pointList = new ArrayList<>();
             double maxX = 0d;
@@ -73,7 +101,7 @@ public class CornerCheck {
             double minX = 10000d;
             double minY = 100000d;
             for (int i = 0; i < pCorners.length; i++) {
-                Imgproc.circle(dst, pCorners[i], 4, new Scalar(0, 0, 0), Imgproc.FILLED);
+                Imgproc.circle(dst, pCorners[i], 4, new Scalar(255, 0, 255), Imgproc.FILLED);
                 if (pCorners[i].x > 130 && pCorners[i].x < 570 && pCorners[i].y > 200 && pCorners[i].y < 850) {
                     if (pCorners[i].x >= maxX) {
                         maxX = pCorners[i].x;
@@ -144,25 +172,57 @@ public class CornerCheck {
         return matCornerList;
     }
 
-    public static List<Point> detectConerList() {
+    public static List<Point> detectConerList(String filePath) {
         List<Point> result = new ArrayList<>();
         try {
             System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
 
             final int maxCorners = 50, blockSize = 3;
-            final double qualityLevel = 0.01, minDistance = 20.0, k = 0.04;
+            final double qualityLevel = 0.01, minDistance = 10.0, k = 0.04;
             final boolean useHarrisDetector = false;
             MatOfPoint corners = new MatOfPoint();
 
-            Mat src = Imgcodecs.imread("D:\\data\\167.jpg");
+            Mat src = Imgcodecs.imread(filePath);
+//            for (int i=0;i<src.cols();i++){
+//                for(int j=0;j<src.rows();j++){
+//                    if (i > 160 && i < 470 && j > 250 && j < 750) {
+//                        Imgproc.circle(src, new Point(i,j), 1, new Scalar(0, 236, 2), Imgproc.FILLED);
+//                    }
+//                }
+//            }
+            //卷积
+            Mat kernel = new Mat(3, 3, CvType.CV_16SC1);
+            kernel.put(0, 0, 0, -1, 0, -1, 5, -1, 0, -1, 0);
+            Imgproc.filter2D(src, src, src.depth(), kernel);
+            //降噪
+            Imgproc.GaussianBlur(src, src, new Size(3, 3), 0, 0, 1);
             if (src.empty()) {
                 throw new Exception("no file");
             }
             Mat dst = src.clone();
             Mat gray = new Mat();
+            //灰度
             Imgproc.cvtColor(src, gray, Imgproc.COLOR_RGB2GRAY);
-            Imgproc.goodFeaturesToTrack(gray, corners, maxCorners, qualityLevel, minDistance,
-                    new Mat(), blockSize, useHarrisDetector, k);
+            //归一处理
+//            Core.normalize(gray,gray);
+            //Sobel算子
+            Mat grad_x = new Mat(), grad_y = new Mat();
+            Mat abs_grad_x = new Mat(), abs_grad_y = new Mat();
+            int scale = 1;
+            int delta = 0;
+            //Gradient X
+            Imgproc.Sobel(gray, grad_x, CvType.CV_16S, 1, 0, 3, scale, delta, 1);
+            //Gradient y
+            Imgproc.Sobel(gray, grad_y, CvType.CV_16S, 0, 1, 3, scale, delta, 1);
+
+            Core.convertScaleAbs(grad_x, abs_grad_x);
+            Core.convertScaleAbs(grad_y, abs_grad_y);
+
+            /// Total Gradient (approximate)
+            Mat grad = new Mat();
+            Core.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
+            Imgproc.goodFeaturesToTrack(grad, corners, maxCorners, qualityLevel, minDistance, new Mat(), blockSize, useHarrisDetector, k);
+//            Imgproc.goodFeaturesToTrack(gray, corners, maxCorners,qualityLevel,minDistance,new Mat(), blockSize, useHarrisDetector, k);
             Point[] pCorners = corners.toArray();
             List<Point> pointList = new ArrayList<>();
             double maxX = 0d;
@@ -193,10 +253,10 @@ public class CornerCheck {
                 double getX = point.x;
                 double getY = point.y;
                 if ((getY >= (minY + 20) && getY <= (maxY - 20))) {
-                    Imgproc.circle(dst, point, 4, new Scalar(255, 255, 255), Imgproc.FILLED);
+//                    Imgproc.circle(dst, point, 10, new Scalar(0, 255, 255), Imgproc.FILLED);
                 } else {
                     cornerPoints.add(point);
-                    Imgproc.circle(dst, point, 4, new Scalar(0, 0, 255), Imgproc.FILLED);
+//                    Imgproc.circle(dst, point, 10, new Scalar(0, 255, 255), Imgproc.FILLED);
                 }
             }
             Collections.sort(cornerPoints, new Comparator<Point>() {
@@ -220,6 +280,7 @@ public class CornerCheck {
             }
             //右下
             result.add(new Point(cornerPoints.get(3).x + EXPAND_SIZE, cornerPoints.get(3).y + EXPAND_SIZE));
+//            Imgcodecs.imwrite("d://data/111.jpg",dst);
             return result;
         } catch (Exception e) {
             e.printStackTrace();

+ 126 - 0
jeecg-boot-module-system/src/main/java/org/jeecg/modules/demo/opencv/ImageUtils.java

@@ -0,0 +1,126 @@
+package org.jeecg.modules.demo.opencv;
+
+import org.opencv.core.*;
+import org.opencv.imgcodecs.Imgcodecs;
+import org.opencv.imgproc.Imgproc;
+
+public class ImageUtils {
+
+    /**
+     * 按照指定的尺寸截取Mat,坐标原点为左上角
+     *
+     * @param src    源Mat
+     * @param width  width
+     * @param height height
+     * @return 截取后的Mat
+     */
+    public static Mat cutFromCenter(Mat src, int width, int height) {
+        if (width > src.width()) {
+            width = src.width();
+        }
+        if (height > src.height()) {
+            height = src.height();
+        }
+        int originX = (src.width() - width) / 2;
+        int originy = (src.height() - height) / 2;
+        // 截取尺寸
+        Rect rect = new Rect(originX, originy, width, height);
+        return new Mat(src, rect);
+    }
+
+    public static Mat radialBlur(Mat src) {
+        Mat returnMat = new Mat(src.size(), CvType.CV_32FC3);
+        src.convertTo(returnMat, CvType.CV_32FC3);
+        int width = src.width();
+        int height = src.height();
+        double r;
+        double angle;
+        Point center = new Point(width / 2, height / 2);
+        double t1, t2, t3;
+        int new_x, new_y;
+        int Num = 20;
+        for (int y = 0; y < height; y++) {
+            for (int x = 0; x < width; x++) {
+                t1 = 0;
+                t2 = 0;
+                t3 = 0;
+                r = Math.sqrt((y - center.y) * (y - center.y) + (x - center.x) * (x - center.x));
+                angle = Math.atan2((y - center.y), (x - center.x));
+                for (int mm = 0; mm < Num; mm++) {
+                    double tmR = r - mm > 0 ? r - mm : 0.0;
+                    new_x = (int) (tmR * Math.cos(angle) + center.x);
+                    new_y = (int) (tmR * Math.sin(angle) + center.y);
+                    if (new_x < 0) {
+                        new_x = 0;
+                    }
+                    if (new_x > width - 1) {
+                        new_x = width - 1;
+                    }
+                    if (new_y < 0) {
+                        new_y = 0;
+                    }
+                    if (new_y > height - 1) {
+                        new_y = height - 1;
+                    }
+                    t1 = t1 + src.get(new_y, new_x)[0];
+                    t2 = t2 + src.get(new_y, new_x)[1];
+                    t3 = t3 + src.get(new_y, new_x)[2];
+                }
+                returnMat.put(y, x, t1 / Num, t2 / Num, t3 / Num);
+            }
+        }
+        return returnMat;
+    }
+
+    /**
+     * 矩阵横向拼接
+     *
+     * @param matrix1
+     * @param matrix2
+     * @param matrixCom
+     * @return
+     */
+    public static Mat hconcat(Mat matrix1, Mat matrix2, Mat matrixCom) {
+        matrixCom.create(matrix1.rows(), matrix1.cols() + matrix2.cols(), matrix1.type());
+        Mat temp = matrixCom.colRange(0, matrix1.cols());
+        matrix1.copyTo(temp);
+        Mat temp1 = matrixCom.colRange(matrix1.cols(), matrix1.cols() + matrix2.cols());
+        matrix2.copyTo(temp1);
+        return matrixCom;
+    }
+
+    /**
+     * 矩阵纵向拼接
+     *
+     * @param matrix1
+     * @param matrix2
+     * @param matrixCom
+     * @return
+     */
+    public static Mat vconcat(Mat matrix1, Mat matrix2, Mat matrixCom) {
+        matrixCom.create(matrix1.rows() + matrix2.rows(), matrix1.cols(), matrix1.type());
+        Mat temp = matrixCom.rowRange(0, matrix1.rows());
+        matrix1.copyTo(temp);
+        Mat temp1 = matrixCom.rowRange(matrix1.rows(), matrix1.rows() + matrix2.rows());
+        matrix2.copyTo(temp1);
+        return matrixCom;
+    }
+
+    public static void main(String[] args) {
+        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+        Mat image = Imgcodecs.imread("D:\\data\\167.jpg", Imgcodecs.IMREAD_COLOR);
+        Mat bigImamge = new Mat();
+        Mat smallImage = new Mat();
+        Mat halfImage = new Mat();
+        Mat wholeImage = new Mat();
+        Imgproc.resize(image, bigImamge, new Size(image.cols() * 1.25, image.rows() * 1.25));
+        Imgproc.resize(image, smallImage, new Size(image.cols() / 2, image.rows() / 2));
+        hconcat(smallImage, smallImage, halfImage);
+        vconcat(halfImage, halfImage, wholeImage);
+        Mat destImage = cutFromCenter(bigImamge, image.width(), image.height());
+        wholeImage = radialBlur(wholeImage);
+        Mat radialBlur = radialBlur(destImage);
+        Imgcodecs.imwrite("D:\\data\\radialBlur.jpg", radialBlur);
+        Imgcodecs.imwrite("D:\\data\\whole.jpg", wholeImage);
+    }
+}

+ 3 - 4
jeecg-boot-module-system/src/main/java/org/jeecg/modules/demo/opencv/Perspective.java

@@ -13,9 +13,10 @@ import java.util.List;
  */
 public class Perspective {
     public static void main(String[] args) {
-
+        perpectiveImg("D:\\data\\images\\163.jpg", "D:\\data\\fill\\1.jpg", "D:\\data\\video\\163.jpg");
     }
 
+
     public static void perpectiveImg(String backgroundImgPath, String phoneImgPath, String targetFileName) {
         try {
             System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
@@ -24,7 +25,7 @@ public class Perspective {
             Mat dst = Imgcodecs.imread(backgroundImgPath);
             Mat dst1 = dst.clone();
             //透视变换点位
-            List<Point> perspectivePoints = CornerCheck.detectConerList();
+            List<Point> perspectivePoints = CornerCheck.detectConerList(backgroundImgPath);
             //矩形点位
             List<Point> matPoints = CornerCheck.matCornerList(perspectivePoints);
             //读取图像到矩阵中
@@ -37,8 +38,6 @@ public class Perspective {
             Mat dstPoints = Converters.vector_Point_to_Mat(perspectivePoints, CvType.CV_32F);
             Mat perspectiveMmat = Imgproc.getPerspectiveTransform(srcPoints, dstPoints);
             Imgproc.warpPerspective(src, dst, perspectiveMmat, dst.size(), Imgproc.INTER_LINEAR);
-            System.out.println("cols:" + dst1.cols());
-            System.out.println("rows:" + dst1.rows());
             for (int i = 0; i < dst1.cols(); i++) {
                 for (int j = 0; j < dst1.rows(); j++) {
                     Point point = new Point();

+ 61 - 4
jeecg-boot-module-system/src/main/java/org/jeecg/modules/demo/opencv/Test.java

@@ -1,15 +1,72 @@
 package org.jeecg.modules.demo.opencv;
 
+import org.opencv.core.Core;
+import org.opencv.core.Mat;
+import org.opencv.core.Size;
+import org.opencv.imgcodecs.Imgcodecs;
+import org.opencv.imgproc.Imgproc;
+
 public class Test {
     public static void main(String[] args) {
-        String srcPath = "D://data//images/";
-        String targetPath = "D://data//video/";
-        for (int i = 163; i <= 235; i++) {
+        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+        String srcPath = "D:\\data\\images\\";
+        String fillPath = "D:\\data\\fill\\";
+        String targetPath = "D:\\data\\video\\";
+        //1:切分视频
+//        VideoProcessing.grabberVideoFramer("D://data//video.mp4",srcPath);
+//        VideoProcessing.grabberVideoFramer("D://data//fill.mp4",fillPath);
+        //2:合并图片
+        int srcPhoneFrameNumFrom = 163;
+        int changeSenceFrameNumFrom = 234;
+        //2.1 复制原始视频无变化图片
+//        for(int i=1;i<srcPhoneFrameNumFrom;i++){
+//            Mat srcNoChangeImage = Imgcodecs.imread(srcPath+i+".jpg");
+//            Imgcodecs.imwrite(targetPath+i+".jpg",srcNoChangeImage);
+//        }
+        String getImageName = "";
+        //2.2 填充手机内部图片画面
+        for (int i = 163; i < changeSenceFrameNumFrom; i++) {
             String backImg = srcPath + (i) + ".jpg";
-            String phoneImg = srcPath + (i - 163) + ".jpg";
+            String phoneImg = fillPath + (i - 162) + ".jpg";
             String targetImg = targetPath + i + ".jpg";
             Perspective.perpectiveImg(backImg, phoneImg, targetImg);
+            getImageName = targetImg;
         }
+        //2.3 转场动画
+        Mat image = Imgcodecs.imread(getImageName, Imgcodecs.IMREAD_COLOR);
+        //(1)径向模糊图片
+        Mat radialBlur = ImageUtils.radialBlur(image);
+        Imgcodecs.imwrite(targetPath + changeSenceFrameNumFrom + ".jpg", radialBlur);
+        changeSenceFrameNumFrom++;
+        //(2)放大后径向模糊图片
+        Mat bigImamge = new Mat();
+        Imgproc.resize(image, bigImamge, new Size(image.cols() * 1.25, image.rows() * 1.25));
+        Mat destBigImamge = ImageUtils.cutFromCenter(bigImamge, image.width(), image.height());
+        Mat radialBlurDestBigImamge = ImageUtils.radialBlur(destBigImamge);
+        Imgcodecs.imwrite(targetPath + changeSenceFrameNumFrom + ".jpg", radialBlurDestBigImamge);
+        changeSenceFrameNumFrom++;
+        //(3)缩小之后重复平铺加径向模糊
+        Mat smallImage = new Mat();
+        Mat halfImage = new Mat();
+        Mat wholeImage = new Mat();
+        Imgproc.resize(image, smallImage, new Size(image.cols() / 2, image.rows() / 2));
+        ImageUtils.hconcat(smallImage, smallImage, halfImage);
+        ImageUtils.vconcat(halfImage, halfImage, wholeImage);
+        wholeImage = ImageUtils.radialBlur(wholeImage);
+        Imgcodecs.imwrite(targetPath + changeSenceFrameNumFrom + ".jpg", wholeImage);
+        changeSenceFrameNumFrom++;
+        //复制填充视频无变化图片
+//        for(int i=changeSenceFrameNumFrom;i<100000;i++){
+//            int checkNum = i-3-srcPhoneFrameNumFrom+1;
+//            String fillImagePath = fillPath+checkNum+".jpg";
+//            File file = new File(fillImagePath);
+//            if(file.exists()){
+//                Mat srcMat = Imgcodecs.imread(fillImagePath);
+//                Imgcodecs.imwrite(targetPath+i+".jpg",srcMat);
+//            }else{
+//                break;
+//            }
+//        }
     }
 
 }

+ 8 - 7
jeecg-boot-module-system/src/main/java/org/jeecg/modules/demo/opencv/VideoProcessing.java

@@ -15,15 +15,15 @@ public class VideoProcessing {
     public static String videoPath = "D:/data";
 
     //存放截取视频某一帧的图片
-    public static String videoFramesPath = "D:/data/images/";
+    public static String videoFramesPath = "D:/data/test/";
 
     /**
      * 将视频文件帧处理并以“jpg”格式进行存储。
      * 依赖FrameToBufferedImage方法:将frame转换为bufferedImage对象
-     *
+     * 视频帧拆分
      * @param videoFileName
      */
-    public static String grabberVideoFramer(String videoFileName) {
+    public static String grabberVideoFramer(String videoFileName, String filePackageName) {
         //最后获取到的视频的图片的路径
         String videPicture = "";
         //Frame对象
@@ -34,7 +34,7 @@ public class VideoProcessing {
 			 /*
             获取视频文件
             */
-            FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoPath + "/" + videoFileName);
+            FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoFileName);
             fFmpegFrameGrabber.start();
 
             //获取视频总帧数
@@ -48,7 +48,7 @@ public class VideoProcessing {
 				 */
                 if (frame != null) {
                     //文件绝对路径+名字
-                    String fileName = videoFramesPath + String.valueOf(flag) + ".jpg";
+                    String fileName = filePackageName + String.valueOf(flag) + ".jpg";
 
                     //文件储存对象
                     File outPut = new File(fileName);
@@ -64,6 +64,7 @@ public class VideoProcessing {
         return videPicture;
     }
 
+
     public static BufferedImage FrameToBufferedImage(Frame frame) {
         //创建BufferedImage对象
         Java2DFrameConverter converter = new Java2DFrameConverter();
@@ -72,7 +73,7 @@ public class VideoProcessing {
     }
 
     public static void main(String[] args) {
-        String videoFileName = "video.mp4";
-        grabberVideoFramer(videoFileName);
+        String videoFileName = "test.mp4";
+//        grabberVideoFramer(videoFileName,fillPackageName);
     }
 }