简单图像像素精确统计

来源:互联网 发布:越狱软件大全 编辑:程序博客网 时间:2024/06/01 09:55

今天写程序中要知道图像中某块彩色图像的像素分布,于是很自然地想到写个程序去统计一下,于是,想到RGB每个分量都是0-255,于是非常自然地用了int count[256][256][256]……,很快编完,得意地编译运行——直接报错,栈溢出!!!不对,算了下需要的内存大小:内存要64M!(呃,昨天算错了,以为64G来着……我的是32位机)不知道怎么回事,但是似乎是内存不够了。现在还没查出原因。我就考虑那么就缩小内存吧。另外的原因就是考虑运行时间,如果算上所有的像素的话会非常慢。那么,怎么办呢?

难不倒我,我想,因为我统计的区域颜色比较集中,于是我可以想到可以先分别统计每个通道的量,然后过滤掉那些为0的值,可以用几个数组记录每个非零的值以及它们对应的Index,然后重新组合成一个小型的RGB颜色空间,最好还能按统计值从大小输出,于是还需要排序……好了,思路来了~

我用的是OpenCV,比较喜欢么。

然后,文章权当是给大家参考,以及自己留念下,自己没搞ACM,但是这种最实际的问题还是能自己解决的。

#include <cv.h>#include <highgui.h>#include <cxcore.h>#define IMG_B(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x)]#define IMG_G(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 1]#define IMG_R(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 2]#define MAX_RANGE 12//这里是我估计的大小int main(){IplImage* src =cvLoadImage("test.bmp",1);int B[256],G[256],R[256];//放每个通道分量的统计值int tmpB[256],tmpG[256],tmpR[256];//放通道分量中非零的Indexmemset(B,0,sizeof(B));memset(G,0,sizeof(G));memset(R,0,sizeof(R));int tmpb[MAX_RANGE],tmpg[MAX_RANGE],tmpr[MAX_RANGE];//对应上面的Index,//放Index对应的统计值,等于说实现了双向查找memset(tmpb,0,sizeof(tmpb));memset(tmpg,0,sizeof(tmpg));memset(tmpr,0,sizeof(tmpr));for(int y = 0;y < src->height;y++){for(int x = 0;x < src->width;x++){B[IMG_B(src,x,y)]++;G[IMG_G(src,x,y)]++;R[IMG_R(src,x,y)]++;}}int maxB = 0,minB = 255;int maxG = 0,minG = 255;int maxR = 0,minR = 255;freopen("outcome.txt","w+",stdout);int countB = 0;for(int b = 0;b < 256;b++){if(B[b]!= 0){if(maxB < b)maxB = b;if(minB > b)minB = b;tmpb[countB] = b;tmpB[b] = countB++;//printf("B%d color:%d\n",b,B[b]);}}int countG = 0;for(int g = 0;g < 256;g++){if(G[g] != 0){if(maxG < g)maxG = g;if(minG > g)minG = g;tmpg[countG] = g;tmpG[g] = countG++;//printf("G:%d color:%d\n",g,G[g]);}}int countR = 0;for(int r = 0;r < 256;r++){if(R[r] != 0){if(maxR < r)maxR = r;if(minR > r)minR = r;tmpr[countR] = r;tmpR[r] = countR++;//printf("R:%d color:%d\n",r,R[r]);}}//为了排序,直接用一维数组,方便,而且多维似乎不能直接转为一维int num = countB * countG * countR;int* color = (int*)calloc(num,sizeof(int**));for(int y = 0;y < src->height;y++)for(int x = 0;x < src->width;x++){//终于能统计了啊!!!color[tmpB[IMG_B(src,x,y)] * countG * countR + tmpG[IMG_G(src,x,y)] * countR + tmpR[IMG_R(src,x,y)]]++;}int *p = color;for(int i = 0;i < num;i++)//简单排了下序{int max = p[i];int imax = i;for(int j = i + 1;j < num;j++){if(max < p[j]){imax = j;max = p[j];}}if(imax != i){int tmp = p[imax];p[imax] = p[i];p[i] = tmp;}}//我姑且称为小型的RGB色彩空间int index = 0;for(int b = 0;b < countB;b++)for(int g = 0;g < countG;g++)for(int r = 0;r < countR;r++){if(color[index] != 0)printf("B:%3d G:%3d R:%3d ColorCount:%d\n",tmpb[b],tmpg[g],tmpr[r],color[index++]);}printf("maxB:%d maxG:%d maxR:%d\nminB:%d minG:%d minR:%d\n",maxB,maxG,maxR,minB,minG,minR);free(color);}



效果不错,挺快的~

图片在这里

打完收功~

-----------------------------------------------------------------------------------------------------

以上是昨天的版本,发现了很多错误……

-----------------------------------------------------------------------------------------------------

好吧,我错了,错了很离谱,终于明白了,不是内存不够,而是栈堆溢出,昨天的错误提示很明确的,我竟然没好好理解。好吧,换calloc。还有就是排序丢失了RGB数据,得换个方法。于是,现在就出来一个正确无误的版本:

#include <cv.h>#include <highgui.h>#include <cxcore.h>#define IMG_B(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x)]#define IMG_G(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 1]#define IMG_R(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 2]#define MAX_RANGE 256#define Count_Threshold 20//统计数据的阈值,不再以非零为阈值了struct Data//用结构体记录RGB信息,也方便排序{uchar B,G,R,reserve;int count;};static int compare(Data a,Data b)//用在sort中{return a.count > b.count;}int main(){IplImage* src =cvLoadImage("test.bmp",1);//为了排序,直接用一维数组,方便,而且多维似乎不能直接转为一维int num = MAX_RANGE * MAX_RANGE * MAX_RANGE;int* color = (int*)calloc(num,sizeof(int));int maxB = 0,minB = 255;int maxG = 0,minG = 255;int maxR = 0,minR = 255;freopen("outcome.txt","w+",stdout);for(int y = 0;y < src->height;y++)for(int x = 0;x < src->width;x++){color[IMG_B(src,x,y) * MAX_RANGE * MAX_RANGE+ IMG_G(src,x,y) * MAX_RANGE + IMG_R(src,x,y)]++;}vector<Data> data;int index = 0;for(int b = 0;b < MAX_RANGE;b++)for(int g = 0;g < MAX_RANGE;g++)for(int r = 0;r < MAX_RANGE;r++){if(color[index] >= Count_Threshold){if(maxB < b)maxB = b;if(minB > b)minB = b;if(maxG < g)maxG = g;if(minG > g)minG = g;if(maxR < r)maxR = r;if(minR > r)minR = r;Data d;d.B = b;d.G = g;d.R = r;d.count = color[index];data.push_back(d);}index++;}sort(data.begin(),data.end(),compare);//排序for(int i = 0;i < data.size();i++)printf("B:%3d G:%3d R:%3d ColorCount:%d\n",data[i].B,data[i].G,data[i].R,data[i].count);printf("maxB:%d maxG:%d maxR:%d\nminB:%d minG:%d minR:%d\n",maxB,maxG,maxR,minB,minG,minR);free(color);}


总结:

  1. 遇到问题追根求底,别放置一旁不管。
  2. 别被暂时的喜悦冲昏了头脑。
  3. 问题总有解决的方法,走不通的时候换个角度试试。
  4. 快速排序还有链表没有自己实现,偷懒了。找时间试试。


原创粉丝点击