ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

[OpenCV学习日记-java]-15-图像直方图

2020-02-05 19:44:46  阅读:348  来源: 互联网

标签:Imgproc java Mat hist OpenCV 直方图 灰度 new


图像直方图

图像直方图是图像的统计学特征


直方图的计算与显示

对图像进行统计,并且绘制他们各个灰度等级对应的直方图就可以的得到图像的直方图

计算直方图的api如下

calcHist(List<Mat> images, MatOfInt channels, Mat mask, Mat hist, MatOfInt histSize, MatOfFloat ranges)
  • images:输入图像,类型必须相同
  • channels:通道索引列表
  • mask:遮罩层
  • hist:计算得到直方图数据,
  • histSize:直方图的大小
  • ranges:直方图的取值范围

实现代码如下

Mat m = Imgcodecs.imread("C:\\test\\ecy.jpg");
HighGui.imshow("原图",m);

//灰度
Mat m1 = new Mat();
Imgproc.cvtColor(m,m1,Imgproc.COLOR_BGR2GRAY);
HighGui.imshow("灰度",m1);

//添加图像
List<Mat> images = new ArrayList<>();
images.add(m1);


//计算直方图
Mat hist = new Mat();
Imgproc.calcHist(images,new MatOfInt(0),new Mat(),hist,new MatOfInt(256),new MatOfFloat(0,255));

//数值归一化
Core.normalize(hist,hist,0,255,Core.NORM_MINMAX);
int h = hist.rows();

Mat m2 = new Mat(new Size(300,300),m.type(),new Scalar(200,200,200));
float[] histdata = new float[256];

//获取数据
hist.get(0,0,histdata);

//绘制直方图
int x = 20;
int y = 280;//图像区域位置
Imgproc.line(m2,new Point(x,0),new Point(x,y),new Scalar(255,0,0));
Imgproc.line(m2,new Point(x,y),new Point(400,y),new Scalar(255,0,0));

for (int i = 0; i < h - 1; i++) {
    int y1 = (int) histdata[i];
    Rect rect = new Rect();
    rect.x = x+i;
    rect.y = y-y1;
    rect.width= 1;
    rect.height = y1;
    Imgproc.rectangle(m2,rect.tl(),rect.br(),new Scalar(15,15,15));

}

HighGui.imshow("直方图",m2);

在这里插入图片描述


在此之后 我封装了一个Api函数
方便后面直接调用

    /**
     * @param name 显示直方图的窗口名
     * @param gray 灰度图像
     * @return 返回计算后的直方图 hist
     */
    public static Mat showHist(String name,Mat...gray){

    //添加图像
    List<Mat> images = new ArrayList<>(Arrays.asList(gray));  
    
    //计算直方图
    Mat hist = new Mat();
    Imgproc.calcHist(images,new MatOfInt(0),new Mat(),hist,new MatOfInt(256),new MatOfFloat(0,255));

    //数值归一化
    Core.normalize(hist,hist,0,255,Core.NORM_MINMAX);
    int h = hist.rows();

    //创建背景
    Mat histImg = new Mat(new Size(300,300),CvType.CV_8UC3,new Scalar(200,200,200));
    float[] histdata = new float[256];

    //获取直方图数据
    hist.get(0,0,histdata);
    int x = 20;
    int y = 280;
    

    //绘制直方图
    Imgproc.line(histImg,new Point(x,0),new Point(x,y),new Scalar(255,0,0));
    Imgproc.line(histImg,new Point(x,y),new Point(400,y),new Scalar(255,0,0));

    for (int i = 0; i < h - 1; i++) {
        int y1 = (int) histdata[i];
        Rect rect = new Rect();
        rect.x = x+i;
        rect.y = y-y1;
        rect.width= 1;
        rect.height = y1;
        Imgproc.rectangle(histImg,rect.tl(),rect.br(),new Scalar(15,15,15));

    }

    HighGui.imshow(name,histImg);
    return hist;
}

直方图均衡化

直方图均衡化的本质是改变图像的灰度分布,或者说改变图像直方图灰度分布,通过累计灰度级别与相关的数学变换公式,来改变原有的图像直方图灰度分布,然后用改变之后的灰度值重建图像,从而达到调整亮度和对比度的目的。

直方图均衡化Api如下

equalizeHist(Mat src, Mat dst)
  • src:输入 8位灰度图像
  • dst:输出 8位灰度图像

在这里插入图片描述
实现代码如下
showHist 函数是上面整合出来的

Mat m = Imgcodecs.imread("C:\\test\\ecy.jpg");

//灰度
Mat m1 = new Mat();
Imgproc.cvtColor(m,m1,Imgproc.COLOR_BGR2GRAY);

HighGui.imshow("原图灰度",m1);
showHist("原图直方图",m1);

Mat m2 = new Mat();
Imgproc.equalizeHist(m1,m2);//均衡化

HighGui.imshow("均衡化后灰度",m2);
showHist("均衡化后直方图",m2);

直方图比较

直方图的比较可以叫做计算直方图的距离

下面是比较的Api

public static double compareHist(Mat H1, Mat H2, int method){}
  • H1:第一个输入直方图的数据
  • H2:第二个输出直方图的数据
  • method:方法
  • @return 返回比较结果

直方图的比较方法有下面几种

  • HISTCMP_CORREL = 0 相关性
  • HISTCMP_CHISQR = 1 卡方
  • HISTCMP_INTERSECT = 2 相交
  • HISTCMP_BHATTACHARYYA = 3 巴氏距离
  • HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA 海灵格距离(和巴氏一样)
  • HISTCMP_CHISQR_ALT = 4 可选卡方
  • HISTCMP_KL_DIV = 5 K-L散度

下面通过代码演示
结果图示和上一个一样

Mat m = Imgcodecs.imread("C:\\test\\ecy.jpg");

//灰度
Mat m1 = new Mat();
Imgproc.cvtColor(m,m1,Imgproc.COLOR_BGR2GRAY);
HighGui.imshow("原图灰度",m1);

Mat hist1 = showHist("原图直方图",m1);

Mat m2 = new Mat();
Imgproc.equalizeHist(m1,m2);

HighGui.imshow("均衡化后灰度",m2);

Mat hist2 = showHist("均衡化后直方图",m2);

//开始计算距离
double d;
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_CORREL);
System.out.println("相关性:"+d);
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_CHISQR);
System.out.println("卡方:"+d);
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_INTERSECT);
System.out.println("巴氏距离:"+d);
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_HELLINGER);
System.out.println("海灵格距离:"+d);
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_CHISQR_ALT);
System.out.println("可选卡方:"+d);
d = Imgproc.compareHist(hist1,hist2,Imgproc.HISTCMP_KL_DIV);
System.out.println("K-L散度:"+d);

输出结果

相关性:0.01892496480027808
卡方:171801.74023263433
巴氏距离:9967.928175032139
海灵格距离:0.4559564084806153
可选卡方:14483.22276347663
K-L散度:120281.57980569218

上一篇[OpenCV学习日记-java]-14-轮廓分析

Timeless小帅 发布了40 篇原创文章 · 获赞 38 · 访问量 2万+ 私信 关注

标签:Imgproc,java,Mat,hist,OpenCV,直方图,灰度,new
来源: https://blog.csdn.net/qq_18604209/article/details/104171534

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有