基于图像的主颜色分析
一般来说,直接分析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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!