一般來說,直接分析RGB色彩域的顏色分布不是一個好的思路,我們一般轉換到HSV域來分析。但是本文只要是應網友提問,實現最基本的RGB
色彩域的主顏色分析。
代碼分為以下部分:
1、生成測試圖片。為了測試算法是否准確,主動生成
具有25種不同顏色同比重的圖片(每種4%)的
測試圖片。
////創建具有25種不同顏色同比重的圖片
Mat src = Mat( 250, 250,CV_8UC3,Scalar( 0));
//生成時間種子
time_t t;time( &t);
RNG rng(t);
//創建圖片
for ( int i = 0;i < 250;i += 10)
rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
imshow( "src",src);
imwrite( "e:/template/maincolor.jpg",src);
Mat src = Mat( 250, 250,CV_8UC3,Scalar( 0));
//生成時間種子
time_t t;time( &t);
RNG rng(t);
//創建圖片
for ( int i = 0;i < 250;i += 10)
rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
imshow( "src",src);
imwrite( "e:/template/maincolor.jpg",src);

生成的結果大概是這個樣子的。
2、讀取圖片數據,保存到3維數組中去。
//bgr立方體
int *iTable = new int [ 256, 256, 256];
for ( int b = 0;b < 256;b ++)
{
for ( int g = 0;g < 256;g ++)
{
for ( int r = 0;r < 256;r ++)
{
iTable[b,g,r] = 0;
}
}
}
//出現過的顏色
vector <Vec3b > colorAppeared;
//讀取數據
for ( int i = 0;i <src.cols;i ++)
{
for ( int j = 0;j <src.rows;j ++)
{
int b = src.at <Vec3b >(i,j)[ 0];
int g = src.at <Vec3b >(i,j)[ 1];
int r = src.at <Vec3b >(i,j)[ 2];
if (iTable[b,g,r] == 0)
colorAppeared.push_back(src.at <Vec3b >(i,j));
iTable[b,g,r] ++;
}
}
int *iTable = new int [ 256, 256, 256];
for ( int b = 0;b < 256;b ++)
{
for ( int g = 0;g < 256;g ++)
{
for ( int r = 0;r < 256;r ++)
{
iTable[b,g,r] = 0;
}
}
}
//出現過的顏色
vector <Vec3b > colorAppeared;
//讀取數據
for ( int i = 0;i <src.cols;i ++)
{
for ( int j = 0;j <src.rows;j ++)
{
int b = src.at <Vec3b >(i,j)[ 0];
int g = src.at <Vec3b >(i,j)[ 1];
int r = src.at <Vec3b >(i,j)[ 2];
if (iTable[b,g,r] == 0)
colorAppeared.push_back(src.at <Vec3b >(i,j));
iTable[b,g,r] ++;
}
}
3、將數組結果保存到vector中,使用標准庫的排序方法。需要注意的是這里重載了vector的比較函數
//重載用於排序的比較函數
bool Comp( const std : :pair <Vec3b, int > &a, const std : :pair <Vec3b, int > &b)
{
return a.second > b.second;
}
//將出現過的數據插入標准庫
for ( int i = 0;i <colorAppeared.size();i ++)
{
Vec3b vec3b = colorAppeared[i];
int b = vec3b[ 0];
int g = vec3b[ 1];
int r = vec3b[ 2];
std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
result.push_back(apair);
}
//進行排序
sort(result.begin(),result.end(),Comp);
bool Comp( const std : :pair <Vec3b, int > &a, const std : :pair <Vec3b, int > &b)
{
return a.second > b.second;
}
//將出現過的數據插入標准庫
for ( int i = 0;i <colorAppeared.size();i ++)
{
Vec3b vec3b = colorAppeared[i];
int b = vec3b[ 0];
int g = vec3b[ 1];
int r = vec3b[ 2];
std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
result.push_back(apair);
}
//進行排序
sort(result.begin(),result.end(),Comp);
4、顯示最后結果
////顯示結果 前20
Mat matResult = Mat( 200, 200,CV_8UC3,Scalar( 0));
for ( int i = 0;i < 20;i ++)
{
Vec3b vec3b = result[i].first;
int iint = result[i].second;
float dpercent = ( float)iint / (src.rows * src.cols);
rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
printf( "第%d種顏色,占比例為%f\n",i + 1,( float)dpercent);
}
imshow( "matResult",matResult);
Mat matResult = Mat( 200, 200,CV_8UC3,Scalar( 0));
for ( int i = 0;i < 20;i ++)
{
Vec3b vec3b = result[i].first;
int iint = result[i].second;
float dpercent = ( float)iint / (src.rows * src.cols);
rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
printf( "第%d種顏色,占比例為%f\n",i + 1,( float)dpercent);
}
imshow( "matResult",matResult);

5、完整的代碼如下。感謝閱讀,希望有所收獲,歡迎交流。
// jsxyhelu (jsxyhelu@foxmail.com)
# include "stdafx.h"
# include <opencv2 /core /utility.hpp >
# include "opencv2/imgproc.hpp"
# include "opencv2/imgcodecs.hpp"
# include "opencv2/highgui.hpp"
# include <opencv2 /photo.hpp >
# include <fstream >
# include <iostream >
using namespace cv;
using namespace std;
//重載用於排序的比較函數
bool Comp( const std : :pair <Vec3b, int > &a, const std : :pair <Vec3b, int > &b)
{
return a.second > b.second;
}
int main( int argc, const char * * argv )
{
////創建具有25種不同顏色同比重的圖片
Mat src = Mat( 250, 250,CV_8UC3,Scalar( 0));
//生成時間種子
time_t t;time( &t);
RNG rng(t);
//創建圖片
for ( int i = 0;i < 250;i += 10)
rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
imshow( "src",src);
imwrite( "e:/template/maincolor.jpg",src);
////進行主要顏色分析
//用於保存當前出現過的顏色數據結構
std : :vector <std : :pair <Vec3b, int >> result;
//bgr立方體
int *iTable = new int [ 256, 256, 256];
for ( int b = 0;b < 256;b ++)
{
for ( int g = 0;g < 256;g ++)
{
for ( int r = 0;r < 256;r ++)
{
iTable[b,g,r] = 0;
}
}
}
//出現過的顏色
vector <Vec3b > colorAppeared;
//讀取數據
for ( int i = 0;i <src.cols;i ++)
{
for ( int j = 0;j <src.rows;j ++)
{
int b = src.at <Vec3b >(i,j)[ 0];
int g = src.at <Vec3b >(i,j)[ 1];
int r = src.at <Vec3b >(i,j)[ 2];
if (iTable[b,g,r] == 0)
colorAppeared.push_back(src.at <Vec3b >(i,j));
iTable[b,g,r] ++;
}
}
//將出現過的數據插入標准庫
for ( int i = 0;i <colorAppeared.size();i ++)
{
Vec3b vec3b = colorAppeared[i];
int b = vec3b[ 0];
int g = vec3b[ 1];
int r = vec3b[ 2];
std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
result.push_back(apair);
}
//進行排序
sort(result.begin(),result.end(),Comp);
////顯示結果 前20
Mat matResult = Mat( 200, 200,CV_8UC3,Scalar( 0));
for ( int i = 0;i < 20;i ++)
{
Vec3b vec3b = result[i].first;
int iint = result[i].second;
float dpercent = ( float)iint / (src.rows * src.cols);
rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
printf( "第%d種顏色,占比例為%f\n",i + 1,( float)dpercent);
}
imshow( "matResult",matResult);
waitKey();
return 0;
}
# include "stdafx.h"
# include <opencv2 /core /utility.hpp >
# include "opencv2/imgproc.hpp"
# include "opencv2/imgcodecs.hpp"
# include "opencv2/highgui.hpp"
# include <opencv2 /photo.hpp >
# include <fstream >
# include <iostream >
using namespace cv;
using namespace std;
//重載用於排序的比較函數
bool Comp( const std : :pair <Vec3b, int > &a, const std : :pair <Vec3b, int > &b)
{
return a.second > b.second;
}
int main( int argc, const char * * argv )
{
////創建具有25種不同顏色同比重的圖片
Mat src = Mat( 250, 250,CV_8UC3,Scalar( 0));
//生成時間種子
time_t t;time( &t);
RNG rng(t);
//創建圖片
for ( int i = 0;i < 250;i += 10)
rectangle(src,Point( 0,i),Point(src.cols,i + 9),Scalar(rng.uniform( 0, 255),rng.uniform( 0, 255),rng.uniform( 0, 255)), - 1);
imshow( "src",src);
imwrite( "e:/template/maincolor.jpg",src);
////進行主要顏色分析
//用於保存當前出現過的顏色數據結構
std : :vector <std : :pair <Vec3b, int >> result;
//bgr立方體
int *iTable = new int [ 256, 256, 256];
for ( int b = 0;b < 256;b ++)
{
for ( int g = 0;g < 256;g ++)
{
for ( int r = 0;r < 256;r ++)
{
iTable[b,g,r] = 0;
}
}
}
//出現過的顏色
vector <Vec3b > colorAppeared;
//讀取數據
for ( int i = 0;i <src.cols;i ++)
{
for ( int j = 0;j <src.rows;j ++)
{
int b = src.at <Vec3b >(i,j)[ 0];
int g = src.at <Vec3b >(i,j)[ 1];
int r = src.at <Vec3b >(i,j)[ 2];
if (iTable[b,g,r] == 0)
colorAppeared.push_back(src.at <Vec3b >(i,j));
iTable[b,g,r] ++;
}
}
//將出現過的數據插入標准庫
for ( int i = 0;i <colorAppeared.size();i ++)
{
Vec3b vec3b = colorAppeared[i];
int b = vec3b[ 0];
int g = vec3b[ 1];
int r = vec3b[ 2];
std : :pair <Vec3b, int > apair(vec3b,iTable[b,g,r]);
result.push_back(apair);
}
//進行排序
sort(result.begin(),result.end(),Comp);
////顯示結果 前20
Mat matResult = Mat( 200, 200,CV_8UC3,Scalar( 0));
for ( int i = 0;i < 20;i ++)
{
Vec3b vec3b = result[i].first;
int iint = result[i].second;
float dpercent = ( float)iint / (src.rows * src.cols);
rectangle(matResult,Point( 0,i * 10),Point( 200,i * 10 + 9),vec3b, - 1);
printf( "第%d種顏色,占比例為%f\n",i + 1,( float)dpercent);
}
imshow( "matResult",matResult);
waitKey();
return 0;
}