我使用bytefish的代码来计算图像的局部二值模式(LBP)空间均匀直方图。我正在使用spatial_histogram函数来计算局部图像块的直方图。每个计算的补丁的大小为256,因此最终的Mat hist文件大小为1x(n * 256)。我想要了解的是如何将直方图实现转换为统一的直方图实现。实现的直方图代码如下:
void lbp::histogram_(const Mat& src, Mat& hist, int numPatterns) {
hist = Mat::zeros(1, numPatterns, CV_32SC1);
for(int i = 0; i < src.rows; i++) {
for(int j = 0; j < src.cols; j++) {
int bin = src.at<_Tp>(i,j);
hist.at<int>(0,bin) += 1;
}
}
统一过程基于以下文章(针对本地二进制模式) here。 如果二进制模式包含从0到1的最多两个按位转换,或者当位模式被认为是圆形时,则本地二进制模式称为均匀。
答案 0 :(得分:1)
[edit2]色彩还原
这很简单,只需通过表格uniform[256]
进行重新加工就与统一直方图无关!!!
为每种可能的颜色创建翻译(重新着色)表
对于8位灰度,它是256色,例如:
BYTE table[256] = {
0,1,2,3,4,58,5,6,7,58,58,58,8,58,9,10,11,58,58,58,58,58,58,58,12,58,58,58,13,58,
14,15,16,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,17,58,58,58,58,58,58,58,18,
58,58,58,19,58,20,21,22,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
58,58,58,58,58,58,58,58,58,58,58,58,23,58,58,58,58,58,58,58,58,58,58,58,58,58,
58,58,24,58,58,58,58,58,58,58,25,58,58,58,26,58,27,28,29,30,58,31,58,58,58,32,58,
58,58,58,58,58,58,33,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,34,58,58,58,58,
58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,
58,35,36,37,58,38,58,58,58,39,58,58,58,58,58,58,58,40,58,58,58,58,58,58,58,58,58,
58,58,58,58,58,58,41,42,43,58,44,58,58,58,45,58,58,58,58,58,58,58,46,47,48,58,49,
58,58,58,50,51,52,58,53,54,55,56,57 };
您也可以像table[i]=(58*i)/255;
一样进行线性分布计算,但我建议它更像基于直方图示例的重新着色:
//hist[256] - already computed classic histogram
//table[59] - wanted recolor table
void compute_table(int *table,int *hist)
{
int i,c,threshold=1;
for (c=-1,i=0;i<256;i++)
if (hist[i]>threshold) { c++; table[i]=c; }
else table[i]=58;
}
按区域大小或颜色计数等设置阈值......
重新着色
color_59=table[color_256];
重新着色源图像或仅在用于直方图计算之前更改颜色值
就是这样。
[edit1] LBP
我认为计算 LBP 的直方图不是一个好主意
min
和max
颜色然后将颜色转换为二进制
if (color>=(max+min)/2) color=1; else color=0;
现在转移+或它们以形成 LBP 向量
4x4 LBP示例:
LBP =color[0][0];
LBP<<=1; LBP|=color[0][1];
LBP<<=1; LBP|=color[0][2];
...
LBP<<=1; LBP|=color[3][3];
您可以直接在步骤#2
[原始答案] - 现已过时
直方图是不同颜色(阴影)的概率/发生/计数
组合子直方图
只需将它们组合在一起或使用单个hist数组初始化一次,然后只需求它就可以得到它:
??? hist=Mat::zeros(1, numPatterns, CV_32SC1);
void lbp::histogram_(const Mat& src, Mat& hist, int numPatterns, bool init) {
if (init) hist = Mat::zeros(1, numPatterns, CV_32SC1);
for(int i = 0; i < src.rows; i++) {
for(int j = 0; j < src.cols; j++) {
int bin = src.at<_Tp>(i,j);
hist.at<int>(0,bin) += 1;
}
}
第一个补丁调用将init设置为true,其余所有补丁设置为false。 numPatterns
是最大使用颜色+ 1或最大可能颜色数(不是不同颜色数)
如果您想只保存使用的颜色
然后你还需要记住颜色。 int hist[][2],hists=0;
或者使用一些动态列表模板,因为hist计算会改变(会慢得多)。
测试它是否在hist[i][0]==color
如果是,则递增其计数器hist[i][1]++;
如果没有添加新颜色hist[hists][0]=color; hist[hists][1]=1; hists++;
只有当使用的颜色少于可能颜色的一半时,才能节省空间。为了提高性能,您可以正常计算hist,然后以相同的方式重新计算到此列表(而不是粗略的增量部分)