运用javacv对视频做色偏检测

运用java对视频做色偏检测

pom文件

  <dependencies>
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>javacv</artifactId>
      <version>1.5</version>
    </dependency>
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>javacv-platform</artifactId>
      <version>1.5</version>
    </dependency>
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>javacpp</artifactId>
      <version>1.5</version>
    </dependency>
    <dependency>
      <groupId>org.bytedeco.javacpp-presets</groupId>
      <artifactId>opencv-platform</artifactId>
      <version>4.0.1-1.4.4</version>
    </dependency>
    <dependency>
      <groupId>org.bytedeco.javacpp-presets</groupId>
      <artifactId>ffmpeg-platform</artifactId>
      <version>4.1-1.4.4</version>
    </dependency>
  </dependencies>

代码实现:

package main;/**
 * @program: New_javacv
 * @description:
 * @author: Mr.Wang
 * @create: 2021-03-22 09:44
 **/
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.io.IOException;

/**
 * @program: New_javacv
 *
 * @description:
 *
 * @author: li
 *
 * @create: 2021-03-22 09:44
 **/
// cast 计算出的偏差值,小于1表示比较正常,大于1表示存在色偏
//    da 红/绿色偏估计值,da大于0,表示偏红;da小于0表示偏绿
//    db 黄/蓝色偏估计值,db大于0,表示偏黄;db小于0表示偏蓝
public class colour_cast {
    //视频文件路径
//    private static String videoPath = "F:\\dashtest1\\";
    //视频帧图片存储路径
    public static String videoFramesPath = "F:\\javacv_project\\definition\\";
    /**
     * TODO 将视频文件帧处理并以“jpg”格式进行存储。
     * 依赖FrameToBufferedImage方法:将frame转换为bufferedImage对象
     *
     * @param videoFileName
     */
    public static void grabberVideoFramer(String videoFileName) {
        //Frame对象
        Frame frame = null;
        //标识,a表示存在色偏,b表示不存在色偏
        int flag = 0,exist=0,none=0;

        /*
            获取视频文件
         */
        FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoFileName);
        try {
            fFmpegFrameGrabber.start();
            /*
            .getFrameRate()方法:获取视频文件信息,总帧数
             */
            int ftp = fFmpegFrameGrabber.getLengthInFrames();
            System.out.println("时长 " + ftp /
                    fFmpegFrameGrabber.getFrameRate() / 60);
            BufferedImage bImage = null;
            System.out.println("开始运行视频提取帧,耗时较长");
            while (flag <= ftp) {
                //文件绝对路径+名字
                String fileName = videoFramesPath + "/img_" + String.valueOf(flag) + ".jpg";
                //文件储存对象
                File outPut = new File(fileName);
                //获取帧
                frame = fFmpegFrameGrabber.grabImage();
                if (frame != null&&(flag%1000)==0) {
//       每1000帧取一帧图像
             ImageIO.write(FrameToBufferedImage(frame), "jpg", outPut);
                    BufferedImage bufferedImage = FrameToBufferedImage(frame);
                    Mat srcImage=bufferToMartix(bufferedImage);
                    //读取图片成为mat类
//                    Mat srcImage = Imgcodecs.imread(outPut.getAbsolutePath());

                    Mat dstImage = new Mat();
                    //  将RGB图像转变到CIE L*a*b*
                    Imgproc.cvtColor(srcImage, dstImage, Imgproc.COLOR_BGR2Lab);
                   //用于记录a/b轴的平均值
                    float a=0,b=0;
//                    记录a/b轴每个色度的出现次数
                    int HistA[] = new int[256],HistB[] = new int[256];
                    for(int i=0;i<256;i++)
                    {
                        HistA[i]=0;
                        HistB[i]=0;
                    }
                  //  int size= (int)dstImage.total() * dstImage.channels();
                    for(int i=0;i < dstImage.rows(); i++)
                    {
                        for(int j=0;j< dstImage.cols(); j++)
                        {
                            //在计算过程中,要考虑将CIEL*a*b*空间还原后同
                            a+=(float)(dstImage.get(i,j)[1]-128);
                            b+=(float)(dstImage.get(i,j)[2]-128);
                             int x=(int)dstImage.get(i,j)[1];
                             int y=(int)dstImage.get(i,j)[2];
                            HistA[x]++;
                            HistB[y]++;
                        }
                    }
                    float  da=a/(float)(dstImage.rows() * dstImage.cols());
                    float db=b/(float)(dstImage.rows() * dstImage.cols());
                    float D= (float)Math.sqrt(da*da+db*db);
                    float Ma=0,Mb=0;
                    for(int i=0;i<256;i++)
                    {
                        //计算范围-128~127
                        Ma+=Math.abs(i-128-da)*HistA[i];
                        Mb+=Math.abs(i-128-db)*HistB[i];
                    }
                    Ma/=(float)(dstImage.rows() * dstImage.cols());
                    Mb/=(float)(dstImage.rows() * dstImage.cols());
                    float M=(float)Math.sqrt(Ma*Ma+Mb*Mb);
                    //D:代表平均色度,M代表色度平均度
                    float K=D/M;
                    float cast =K;

               System.out.printf("色偏指数: %f\n",cast);
                    if(cast>1.1) {
                         exist++;
//                        System.out.printf("存在色偏\n");
//                        return true;
                    }
                    else {
//                        System.out.printf("不存在色偏\n");
//                        return false;
                        none++;
                    }
                }
                flag++;

            }
            if(exist>none){
                System.out.println("视频存在色偏");
            }else{
                System.out.println("视频几乎无色偏");
            }
            System.out.println("============运行结束============");
            System.out.println("总共"+flag+"帧");
            fFmpegFrameGrabber.stop();
        } catch (IOException E) {
        }
    }
    //将帧转换为bufferedimage
    public static BufferedImage FrameToBufferedImage(Frame frame) {
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bufferedImage = converter.getBufferedImage(frame);
        return bufferedImage;
    }
    //将bufferimage转换为mat
    public static Mat bufferToMartix(BufferedImage image) {
        Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
        byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        if (mat != null) {
            try {
                mat.put(0, 0, data);
            } catch (Exception e) {
                return null;
            }
        }
        return mat;
    }
    /*
        测试.....
     */
    public static void main(String[] args) {
     System.load("F:\\基本技能\\New_javacv\\opencv_java340-x64.dll");
        grabberVideoFramer("F:\\javacv_project\\color_cast.avi");
    }
//    public static String getVideoPath() {
//        return videoPath;
//    }
//    public static void setVideoPath(String videoPath) {
//        colour_cast.videoPath = videoPath;
//    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值