• 数字图像处理作业使用OpenCV


    第二次作业需要打印出来灰度直方图,当然不能使用ocv的自带calcHist函数来得到Mat对象了……结果上网搜索怎么用自己的数据创建直方图,搜到的都是直接用函数的_(:з」∠)_

    结果这个地方拖了好久呵呵呵呵呵呵呵。最后还是努力耐下性子来对照网上绘制灰度直方图的代码来看到底内藏什么玄机,结果发现其实真的,没什么,大不了(笑)(哭)。

    基本思路:

      建立一个Mat对象作为直方图的画布,将256个灰度级的数值的直方用rectangle或者line一个一个画出来。

    ……简直简单到我无法想象_(:з」∠)_论耐下性子的重要性(。

    除此之外,还需要知道ocv里的坐标体系。原点是在图像的左上角,x轴是图像上方的边缘,y轴是图像左边的边缘。这一点对于画基本图形是非常重要的。

    首先转载一下网上csdn博客xiaowei_cqu的画灰度直方图的代码。

    //绘制灰度直方图
    int main(  )
    {
        Mat src,gray;
        src=imread("baboon.jpg");
        cvtColor(src,gray,CV_RGB2GRAY);
        int bins = 256;
        int hist_size[] = {bins};
        float range[] = { 0, 256 };
        const float* ranges[] = { range};
        MatND hist;
        int channels[] = {0};
    //使用ocv自带函数计算灰度直方图
        calcHist( &gray, 1, channels, Mat(), // do not use mask
            hist, 1, hist_size, ranges,
            true, // the histogram is uniform
            false );
    
    //画出直方图
        double max_val;
        minMaxLoc(hist, 0, &max_val, 0, 0);
        int scale = 2;
        int hist_height=256;
        Mat hist_img = Mat::zeros(hist_height,bins*scale, CV_8UC3);
        for(int i=0;i<bins;i++)
        {
            float bin_val = hist.at<float>(i); 
            int intensity = cvRound(bin_val*hist_height/max_val);  //要绘制的高度
            rectangle(hist_img,Point(i*scale,hist_height-1),
                Point((i+1)*scale - 1, hist_height - intensity),
                CV_RGB(255,255,255));
        }
        imshow( "Source", src );
        imshow( "Gray Histogram", hist_img );
        waitKey(10000000000);
        return 0;
    }    

    我需要关注的就是【画出直方图】这一块代码。

    可以发现,这个直方图是将每一个区间长度定位2pixel,直方图画布的长是【区间数 * 区间长度】= 256*2 = 512,高为256,初始化为一幅黑色画布。

    进入画直方图阶段,简单来说,就是取出图像的灰度频率表(每个灰度值占整个图像的像素数)的每一个值,计算出绘制高度,根据这个绘制高度去划线或者矩形。

    绘制高度,是【矩形高度 * 画布高度 / 最大矩形高度】,为啥要这样设置,应该是跟概率统计直方图有关吧……

    这里使用了rectangle即画矩形来代表每一个区间。

    //参数为:承载对象(此处为Mat)、左下角点、右上角点、颜色、粗细、大小
    rectangle(picture,a,center,Scalar(255,0,0));
    

    当然也可以用line即线段来代表一个区间。

    //参数为:承载对象(此处为Mat)、起始点、结束点、颜色、粗细、线型  
    line(picture,a,center,Scalar(255,0,0));  

    由于ocv一般的坐标体系如上所述,所以对应习惯的坐标系,x轴应该是坐标为(x, 255)的线,至于为什么是255,是为了能显示出高度为0的区间。

    而rectangle的两个点的参数为什么是这样,让我来画一张示意图。

    假设此时要要画(Point(0, hist_height - 1), Point(1, hist_height-intensity))的矩形。

     按照以上的代码修改之后,我也可以用自己的数据来画一个直方图了QAQ感天动地。

    以上内容参考了这几个博客,包括直方图绘制代码,OCV的坐标体系和画基本图形的函数,感谢分享!

    http://blog.csdn.net/panda1234lee/article/details/14162965

    http://blog.csdn.net/thefutureisour/article/details/7523925

    http://blog.csdn.net/xiaowei_cqu/article/details/8833799

    http://blog.csdn.net/xiaowei_cqu/article/details/7600666

  • 相关阅读:
    pycharm运行Django项目,提示UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6
    linux环境下 python环境import找不到自定义的模块
    python-获取URL中的json数据
    python-Excel读取-合并单元格读取
    自动驾驶控制算法第七讲 离散规划轨迹的误差计算
    静态语言和动态语言的区别
    Python函数-导入模块的顺序及原理
    使用Visual Studio查看C++类内存分布
    在VisualStudio调试器中使用内存窗口和查看内存分布
    visual studio 2019工具里添加开发中命令提示符的方法
  • 原文地址:https://www.cnblogs.com/muluo0107/p/4152185.html
Copyright © 2020-2023  润新知