运用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;
// }
}