OpenCV手工實現灰度及RGB直方圖


 

手工實現灰度及RGB直方圖 !庫

1. 灰度圖像直方圖

算法

1. 圖片灰度化;

2. 遍歷Mat,統計各灰度級的像素個數;

3. 根據opencv畫點線函數,繪制坐標軸及像素分布圖

源碼(編譯環境:VS2017+OpenCV) 補充:三通道直方圖(即RGB彩色圖象直方圖在后面)

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <opencv2/opencv.hpp>
 5 #include <opencv2/imgproc/imgproc.hpp>
 6 #include <opencv2/core/core.hpp>
 7 #include <opencv2/highgui/highgui.hpp>
 8 using namespace cv;
 9 using namespace std;
10 //直方圖繪制函數,參數vector<int> nums 是灰度圖片256級灰度的像素個數
11 void drawHist(vector<int> nums)
12 {
13     Mat hist = Mat::zeros(600, 800, CV_8UC3);
14     auto Max = max_element(nums.begin(), nums.end());//max迭代器類型,最大數目
15     putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
16     //*********繪制坐標系************//
17     Point o = Point(100, 550);
18     Point x = Point(700, 550);
19     Point y = Point(100, 150);
20     //x軸
21     line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
22     //y軸
23     line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);
24 
25     //********繪制灰度曲線***********//
26     Point pts[256];
27     //生成坐標點
28     for (int i = 0; i < 256; i++)
29     {
30         pts[i].x = i * 2 + 100;
31         pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//歸一化到[0, 300]
32         //顯示橫坐標
33         if ((i + 1) % 16 == 0)
34         {
35             string num = format("%d", i + 1);
36             putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
37         }
38     }
39     //繪制線
40     for (int i = 1; i < 256; i++)
41     {
42         line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2);
43     }
44     //顯示圖像
45     imshow("直方圖" ,hist);
46 }
47 //計算直方圖,統計各灰度級像素個數
48 void calHist(const string img)
49 {
50     Mat src, grey;
51     //讀取圖象
52     src = imread(img);
53     if (!src.data)
54     {
55         cout << "Image: " + img + " 讀取失敗" << endl;
56         return;
57     }
58     //先轉為灰度圖
59     cvtColor(src, grey, COLOR_BGR2GRAY);
60     imshow("灰度圖", grey);
61     //計算各灰度級像素個數
62     vector<int> nums(256);
63     for (int i = 0; i < grey.rows; i++)
64     {
65         uchar* p = grey.ptr<uchar>(i);
66         for (int j = 0; j < grey.cols; j++)
67         {
68             nums[p[j]]++;
69         }
70     }
71     drawHist(nums);
72 }
73 
74 int main()
75 {
76     string img = "D:\\trashBox\\testIMG\\lena.bmp";
77     calHist(img);
78     
79     waitKey(0);
80     return 0;
81 }

效果圖

直方圖hist

 2. RGB彩色圖象直方圖

源碼

#include <iostream>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;

//單通道圖片直方圖繪制
void drawHist(vector<int> nums)
{
    Mat hist = Mat::zeros(600, 800, CV_8UC3);
    auto Max = max_element(nums.begin(), nums.end());//max迭代器類型,最大數目
    putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
    //*********繪制坐標系************//
    Point o = Point(100, 550);
    Point x = Point(700, 550);
    Point y = Point(100, 150);
    //x軸
    line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
    //y軸
    line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);

    //********繪制灰度曲線***********//
    Point pts[256];
    //生成坐標點
    for (int i = 0; i < 256; i++)
    {
        pts[i].x = i * 2 + 100;
        pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//歸一化到[0, 300]
        //顯示橫坐標
        if ((i + 1) % 16 == 0)
        {
            string num = format("%d", i + 1);
            putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
        }
    }
    //繪制線
    for (int i = 1; i < 256; i++)
    {
        line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2);
    }
    //顯示圖像
    imshow("直方圖" ,hist);
}

//三通道圖片直方圖繪制
void drawHist(vector<int> &r, vector<int> &g, vector<int> &b)
{
    Mat hist = Mat::zeros(600, 800, CV_8UC3);
    putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
    //*********繪制坐標系************//
    Point o = Point(100, 550);
    Point x = Point(700, 550);
    Point y = Point(100, 150);
    //x軸
    line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
    //y軸
    line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);

    //********繪制灰度曲線***********//
    auto Max_r = max_element(r.begin(), r.end());
    auto Max_g = max_element(g.begin(), g.end());
    auto Max_b = max_element(b.begin(), b.end());
    Point pts[3][256];
    //生成坐標點
    for (int i = 0; i < 256; i++)
    {
        pts[0][i].x = i * 2 + 100;
        pts[0][i].y = 550 - int(r[i] * (300.0 / (*Max_r)));//歸一化到[0, 300]
        pts[1][i].x = i * 2 + 100;
        pts[1][i].y = 550 - int(g[i] * (300.0 / (*Max_g)));//歸一化到[0, 300]
        pts[2][i].x = i * 2 + 100;
        pts[2][i].y = 550 - int(b[i] * (300.0 / (*Max_b)));//歸一化到[0, 300]
        //顯示橫坐標
        if ((i + 1) % 16 == 0)
        {
            string num = format("%d", i + 1);
            putText(hist, num, Point(pts[0][i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
        }
    }
    //繪制線
    for (int i = 1; i < 256; i++)
    {
        line(hist, pts[0][i - 1], pts[0][i], Scalar(255, 0, 0), 2);
        line(hist, pts[1][i - 1], pts[1][i], Scalar(0, 255, 0), 2);
        line(hist, pts[2][i - 1], pts[2][i], Scalar(0, 0, 255), 2);
    }
    //顯示圖像
    imshow("直方圖", hist);
}

//灰度直方圖計算
void calHist(const string img)
{
    Mat src, grey;
    //讀取圖象
    src = imread(img);
    if (!src.data)
    {
        cout << "Image: " + img + " 讀取失敗" << endl;
        return;
    }
    //先轉為灰度圖
    cvtColor(src, grey, COLOR_BGR2GRAY);
    imshow("灰度圖", grey);
    //計算各灰度級像素個數
    vector<int> nums(256);
    for (int i = 0; i < grey.rows; i++)
    {
        uchar* p = grey.ptr<uchar>(i);
        for (int j = 0; j < grey.cols; j++)
        {
            nums[p[j]]++;
        }
    }
    drawHist(nums);
}

//多通道直方圖計算
void calHist(const string img, int pattern)
{
    Mat src, grey;
    //讀取圖象
    src = imread(img);
    if (!src.data)
    {
        cout << "Image: " + img + " 讀取失敗" << endl;
        return;
    }
    imshow("原圖像",src);
    //計算各灰度級像素個數
    vector<int> r(256, 0);
    vector<int> g(256, 0);
    vector<int> b(256, 0);
    for (int i = 0; i < src.rows; i++)
    {
        uchar* p = src.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++)
        {
            r[p[j * 3 + 0]]++;
            g[p[j * 3 + 1]]++;
            b[p[j * 3 + 2]]++;
        }
    }
    drawHist(r, g, b);
}

int main()
{
    string img = "D:\\trashBox\\testIMG\\tiger.jpg";
    calHist(img);//計算灰度直方圖
    calHist(img, 0);//計算三色直方圖
    
    waitKey(0);
    return 0;
}

算法

1. 遍歷Mat,統計RGB三通道各灰度級的像素個數;

2. 根據opencv畫點線函數,繪制坐標軸及像素分布圖

效果

 

三色(三通道)直方圖

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM