【图像处理】利用C++编写函数,绘制灰度图像直方图

﹥>﹥吖頭↗ 提交于 2019-12-01 07:21:15

1. 简介

利用OpenCV读取图像,转换为灰度图像,绘制该灰度图像直方图。点击直方图,控制台输出该灰度级像素个数。

2. 原理

(1) 实现原理较为简单,主要利用了OpenCV读取图像,并转换为灰度图像;

    srcImg = imread(" ......");    // “....” 代表图像地址
    if (srcImg.empty()) {
        return -1;
    }
    imshow(WINDOW_SRCIMG, srcImg);
    Mat grayImg;
    cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    imshow(WINDOW_GRAYIMG, grayImg);

(2) 利用Mat类新建一个固定分辨率的画布,统计处于每一灰度级像素个数,在该画布上绘制灰度直方图。

    int nRows = 700,nCols=600;
    Mat g_dstImg(nRows,nCols, CV_8UC1, Scalar::all(0)); // 新建画布

    同时避免画布中该灰度级太高而超出画布范围,在本程序中采用了等比例缩小的方法。

    int MaxCount = arrayMax(grayLevel,256);//寻找在处于某一灰度级中个数最多的像素个数
    yscaleRate =  double(nRows)/MaxCount ;//y缩放比例
    double xscaleRate = nCols / 256;//x缩放比例

3. 实施细节

// 灰度直方图.cpp : 定义控制台应用程序的入口点。
// Topic: 绘制灰度图的直方图;  转载请注明出处:Chen_HW (https://www.cnblogs.com/chen-hw/p/11668119.html)// Env: VS2015 + Debug x64 + OpenCV3.4.1 
// Date:2018.11.22  by Chen_HW
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#define WINDOW_SRCIMG "【源图】"
#define WINDOW_GRAYIMG "【灰度图】"
#define WINDOW_HIST "【直方图】"
using namespace std;
using namespace cv;
int arrayMax(int g_arr[], int num);
Mat drawHist(Mat &g_srcImg);
void MouseHandle(int event, int x, int y, int flags, void *param);
Point clickPoint,displayPoint;
bool downFlag = false;
Mat srcImg;
double yscaleRate = 0;

int main()
{
    system("color 3f");
    srcImg = imread(" ......");    // “....” 代表图像地址
    if (srcImg.empty()) {
        return -1;
    }
    imshow(WINDOW_SRCIMG, srcImg);
    Mat grayImg;
    cvtColor(srcImg, grayImg, CV_BGR2GRAY);
    imshow(WINDOW_GRAYIMG, grayImg);
    Mat histImg = drawHist(grayImg);
    imshow(WINDOW_HIST, histImg);
    setMouseCallback(WINDOW_HIST, MouseHandle, (void *)&histImg);//(void *)&srcImg传递给void *param
    waitKey();
    return 0;
}
Mat drawHist(Mat &g_srcImg) {
    int nRows = 700,nCols=600;
    Mat g_dstImg(nRows,nCols, CV_8UC1, Scalar::all(0)); // 新建画布
    int grayLevel[256] = {0};
    for (int i = 0; i < g_srcImg.rows; ++i) {
        for (int j = 0; j < g_srcImg.cols; ++j) {
            grayLevel[(int)g_srcImg.at<uchar>(i, j)]++;
        }
    }
    int MaxCount = arrayMax(grayLevel,256);//寻找在处于某一灰度级中个数最多的像素个数
    yscaleRate =  double(nRows)/MaxCount ;//y缩放比例
    double xscaleRate = nCols / 256;//x缩放比例
    int yAxis[256], xAxis[257];
    for (int m = 0; m < 256 ; m++) {
        yAxis[m] = int(grayLevel[m]*yscaleRate);
    }
    //绘制直方图
    for (int n = 0; n < 256; n++) {
        if (n == 255) {
            xAxis[n + 1] = xAxis[n];
        }
        rectangle(g_dstImg, Point(xAxis[n], yAxis[n]), Point( xAxis[n+1], 0), Scalar(255), -1);
                                                                           //-1表示填充矩形框;正值表示不填充矩形框,更方便观察灰度级像素个数的分布;
                                                                          //但因为后面需要用到填充的情况,故设置成填充状态

    }

    return g_dstImg;
}
//num:数组元素个数;g_max:返回最大值
int arrayMax(int g_arr[],int num) {
    int g_max = 0;
    int i = 0;
    while (i < num) {
        if ( g_arr[i]>= g_max) {
            g_max = g_arr[i];
            i++;
        }
        else {
            i++;
        }
    }
    
    return g_max;
}
//event 鼠标事件(如按下鼠标左键、左键抬起、鼠标移动等) x、y 鼠标坐标
void MouseHandle(int event, int x, int y, int flags, void *param) {
    Mat &g_srcImg = *(Mat *)(param);
    Mat g_tempImg = g_srcImg.clone();
    int nCount=0;//该列白色像素点个数
    int nLevelCount = 0;
    char text[20];//存储文本信息
    float g_rate;//该列像素点占总像素点个数的比例
    imshow(WINDOW_HIST, g_srcImg);
    switch (event) {
    case EVENT_LBUTTONDOWN:
        clickPoint.x = x;
        clickPoint.y = y;
        downFlag = true;
        break;
    default:
        break;
    }
    if (downFlag) {
        //displayPoint.x = clickPoint.x;
        for (int i = 0; i < g_srcImg.rows; ++i) {
            if (int(g_srcImg.at<uchar>(i, x)) == 255) {
                ++nCount;
            }
        }
        nLevelCount = (nCount / yscaleRate);
        g_rate = float(nCount/ yscaleRate) / (srcImg.rows*srcImg.cols);//此处计算的比例不是精确的
        cout << "该灰度级像素点个数: " << nLevelCount << ";占总像素个数的比例: "<<g_rate << endl;
        sprintf_s(text, "Rate:%f",g_rate );//该灰度级像素个数占总个数的比例;
        putText(g_tempImg, text, clickPoint,FONT_HERSHEY_PLAIN,1,Scalar(255,0,255));
        imshow(WINDOW_HIST, g_tempImg);
        downFlag = false;
    }
}

4. 结果

  结果如下图所示,点击右侧每一级灰度直方图,在控制台中会输出该灰度级像素个数,并显示占总像素比例。

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!