下面是我参考《opencv3编程入门》写的绘制一维直方图的代码
using namespace cv;
using namespace std;
/*--------------------------绘制RGB三色一维直方图-------------------------------------*/
Mat My_Rraw_histogram(Mat* srcImage,int type)  //输入:要处理的灰度图   输出:该图像的直方图
{
 if (type == TYEPE_GRAY)  //一维灰度直方图绘制
 {
  //【1】将原图转化为灰度图
  Mat gray_srcImage;
  cvtColor(*srcImage,gray_srcImage, COLOR_BGR2GRAY);
  //【2】定义变量
  MatND dstHist;
  int dims = 1;  //需要计算的直方图的维数
  float grayranges[] = { 0,255 };
  const float* ranges[] = { grayranges }; //这里需要为const类型
  int size = 256;   //表示的是将统计的灰度值分成的等份
  int Height = 256;
  int channels = 0; //灰度图只有一个0通道
  //【3】计算图像直方图
  calcHist(srcImage, //输入数组
   1, //数组个数
   &channels, //通道索引
   Mat(),//不使用掩膜
   dstHist, //输出的目标直方图
   dims, //需要计算的直方图的维数
   &size, //存放每个维度的直方图尺寸的数组
   ranges); //每一维数值的取值范围 
  int scale = 1;  //scale 每一个像素占的格数
  Mat dstImage(size * scale, size, CV_8U, Scalar(0));  //长 :size*scale ,宽:size ,值为0
  //【4】获取最大值和最小值
  double minVal = 0;
  double maxVal = 0;
  minMaxLoc(dstHist, &minVal, &maxVal, 0, 0);  //获得直方图中最大值和最小值
  //【5】绘制出直方图
  int hpt = saturate_cast<int>(0.9 * Height);   //saturate_cast 是溢出保护    大概意思 :if(data<int的负范围)  data = 负最大; else if (data > int的正范围) data = int 正最大;
  for (int i = 0;i < 256;i++)
  {
   float binVal = dstHist.at<float>(i);
   int realVal = saturate_cast<int>(binVal * hpt / maxVal);  //在图像上的高度 = 像素数目/像素值最大数目 * 0.9*256   这里0.9是为了削减图像像素高度,因为最大的时候会触及顶端不美观
   rectangle(dstImage, Point(i * scale, Height - 1), Point((i + 1) * scale - 1, Height - realVal), Scalar(255));
   //要进行绘制的目标图像 矩形的左下顶点 矩阵对角线上的右上顶点 线条的颜色(RGB)或亮度(灰度图)  一共要绘制256个矩形
  }
  return dstImage;
 }
 else if (type == TYEPE_RGB)
  {
    //【1】定义变量
    MatND redHist,greenHist,blueHist;
    int dims = 1;   //需要计算的直方图的维数
    float grayranges[] = { 0,256 };
    const float* ranges[] = { grayranges }; //这里需要为const类型
    int size = 256;     //表示的是将统计的灰度值分成的等份
    int channels_r[] = { 2 }; 
    int channels_g[] = { 1 }; 
    int channels_b[] = { 0 }; 
    //疑问 : RGB图像的R、G、B是对应channel[0]、channel[1]、channel[2]还是对应channel[2]、channel[1]、channel[0] ?
    //经过验证是channel[2]、channel[1]、channel[0]
    //【2】计算图像直方图
    //--------------------red--------------------------
    calcHist(srcImage,  //输入数组
      1,  //数组个数
      channels_r, //通道索引
      Mat(),//不使用掩膜
      redHist,  //输出的目标直方图
      dims, //需要计算的直方图的维数
      &size,  //存放每个维度的直方图尺寸的数组
      ranges,//每一维数值的取值范围 
      true,//指示直方图是否均匀的标识符,true表示均匀的直方图
      false); //累计标识符,false表示直方图在配置阶段会被清零
    //--------------------green--------------------------
    calcHist(srcImage,  //输入数组
      1,  //数组个数
      channels_g, //通道索引
      Mat(),//不使用掩膜
      greenHist,  //输出的目标直方图
      dims, //需要计算的直方图的维数
      &size,  //存放每个维度的直方图尺寸的数组
      ranges,//每一维数值的取值范围 
      true,//指示直方图是否均匀的标识符,true表示均匀的直方图
      false); //累计标识符,false表示直方图在配置阶段会被清零
    //--------------------blue--------------------------
    calcHist(srcImage,  //输入数组
      1,  //数组个数
      channels_b, //通道索引
      Mat(),//不使用掩膜
      blueHist, //输出的目标直方图
      dims, //需要计算的直方图的维数
      &size,  //存放每个维度的直方图尺寸的数组
      ranges,//每一维数值的取值范围 
      true,//指示直方图是否均匀的标识符,true表示均匀的直方图
      false); //累计标识符,false表示直方图在配置阶段会被清零
    //【3】获取最大值和最小值
    double minVal_r = 0, minVal_g = 0, minVal_b = 0;
    double maxVal_r = 0, maxVal_g = 0,maxVal_b = 0;
    minMaxLoc(redHist, &minVal_r, &maxVal_r, 0, 0);   //获得r直方图中最大值和最小值
    minMaxLoc(greenHist, &minVal_g, &maxVal_g, 0, 0);   //获得g直方图中最大值和最小值
    minMaxLoc(blueHist, &minVal_b, &maxVal_b, 0, 0);    //获得b直方图中最大值和最小值
    int scale = 1;    //scale 每一个像素占的格数
    int Height = 256; //直方图高度
    Mat dstImage(Height, size*3, CV_8UC3, Scalar(0,0,0));   //长 :size*scale ,宽:size*3 ,值为0  将三个直方图横放在一起
    //【4】绘制出直方图
    int hpt = saturate_cast<int>(0.9 * Height);     //saturate_cast 是溢出保护    大概意思 :if(data<int的负范围)  data = 负最大; else if (data > int的正范围) data = int 正最大;
    for (int i = 0;i < 256;i++)
    {
      float binVal_r = redHist.at<float>(i);
      float binVal_g = greenHist.at<float>(i);
      float binVal_b = blueHist.at<float>(i);
      //疑问:是否存在一张图片中maxVal_r or maxVal_g or maxVal_b 有一个值为0?这样算出来的值将会是0/0, 而实际值应该是 0
      int intensityl_r = saturate_cast<int>(binVal_r * hpt / maxVal_r);   //在图像上的高度 = 像素数目/像素值最大数目 * 0.9*256   这里0.9是为了削减图像像素高度,因为最大的时候会触及顶端不美观
      int intensityl_g = saturate_cast<int>(binVal_g * hpt / maxVal_g);
      int intensityl_b = saturate_cast<int>(binVal_b * hpt / maxVal_b);
      
      rectangle(dstImage, Point(i * scale, Height - 1), Point((i + 1) * scale - 1, Height - intensityl_r), Scalar(0,0,255));
      rectangle(dstImage, Point((i+size)* scale, Height - 1), Point((i + size + 1)* scale - 1, Height - intensityl_g), Scalar(0,255,0));
      rectangle(dstImage, Point((i + 2*size)* scale, Height - 1), Point((i + 2*size + 1)* scale - 1, Height - intensityl_b), Scalar(255,0,0));
      //要进行绘制的目标图像 矩形的左下顶点 矩阵对角线上的右上顶点 线条的颜色(RGB)或亮度(灰度图)  一共要绘制256个矩形
    }
    return dstImage;
  } 
else
  {
  }
}
//主函数
int main()
{
  //【1】载入原图
  Mat srcImage = imread("D:\\opencv_picture_test\\RGB纯色图\\red.jpg", 2|4);     //原图
  //Mat srcImage = imread("D:\\opencv_picture_test\\JQ\\JQ14.jpg", 2 | 4);      //原图
  namedWindow("原图", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口
  imshow("原图", srcImage);
  if (srcImage.empty())
  {
    printf("Could not find the image!\n");
    return -1;
  }
  Mat dstImage = My_Rraw_histogram(&srcImage, TYEPE_RGB);
  namedWindow("一维直方图", WINDOW_NORMAL);//WINDOW_NORMAL允许用户自由伸缩窗口
  imshow("一维直方图", dstImage);
  waitKey(0);
  return 0;
}下面是代码实现的效果

 纯红时,cahnnel【2】值为255的像素个数最多,其他为0,channel【1】和channel【0】值为0的像素个数最多,其他为0。
                
                










