我想这是一个简单的问题(我来自Java),但我无法弄清楚它是如何工作的。
我只想将vector元素递增1。原因是,我想从图像值中计算直方图。但无论我尝试什么,我都可以完成为向量赋值。但是不要把它增加一个!
这是我的直方图功能:
void histogram(unsigned char** image, int height,
int width, vector<unsigned char>& histogramArray) {
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
// histogramArray[1] = (int)histogramArray[1] + (int)1;
// add histogram position by one if greylevel occured
histogramArray[(int)image[i][j]]++;
}
}
// display output
for (int i = 0; i < 256; i++) {
cout << "Position: " << i << endl;
cout << "Histogram Value: " << (int)histogramArray[i] << endl;
}
}
但无论我尝试将其中一个添加到histogramArray位置,它都会导致输出中只有0。我只允许分配具体的值,如:
histogramArray[1] = 2;
有简单易行的方法吗?我虽然希望迭代器在这一点上不是必要的,因为我知道exakt索引位置,我想增加一些东西。
编辑: 我很抱歉,我的问题应该更准确,谢谢你的帮助!上面的代码是有效的,但它显示了直方图中的不同平均值(大约90的差异)。此外,直方图值与图形程序中的方式不同 - 即使图像值完全相同!这就是为什么我调查这个函数并发现如果我将直方图设置为零然后只是尝试增加一个元素,没有任何反应!这是上面评论的代码:
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
histogramArray[1]++;
// add histogram position by one if greylevel occured
// histogramArray[(int)image[i][j]]++;
}
}
因此位置1保持为0,而不是具有值height * width。正因为如此,我认为正确计算histogramArray [image [i] [j]] ++;也没有正常工作。
你对此有任何解释吗?这是我的主要问题,对不起。
为了完整起见,这是我对直方图的平均函数:
unsigned char meanHistogram(vector<unsigned char>& histogram) {
int allOccurences = 0;
int allValues = 0;
for (int i = 0; i < 256; i++) {
allOccurences += histogram[i] * i;
allValues += histogram[i];
}
return (allOccurences / (float) allValues) + 0.5f;
}
我将图像初始化为:
unsigned char** image= new unsigned char*[width];
for (int i = 0; i < width; i++) {
image[i] = new unsigned char[height];
}
但是初始化代码应该没有任何问题,因为所有其他计算都能很好地工作,并且我能够操作并保护原始图像。但这是真的,我应该改变宽度和高度 - 因为我只有方形图像到目前为止无关紧要。 直方图就像这样创建,然后调用函数:
vector<unsigned char> histogramArray(256);
histogram(array, adaptedHeight, adaptedWidth, histogramArray);
那么你有什么线索为什么这部分histogramArray [1] ++;不要增加我的直方图? histogramArray [1]一直保持为0! histogramArray [1] = 2;工作得很好。还有histogramArray [(int)image [i] [j]] ++;似乎在计算一些东西,但正如我所说,我认为这是错误的计算。 我非常感谢任何帮助!我使用2D数组的原因仅仅是因为它被要求。我更喜欢1D版本,因为它更简单!
答案 0 :(得分:1)
您可以看到,代码中的当前问题是不递增值而不是分配给它; 这是您索引图像的方式。您编写histogram
函数和图像访问部分的方式对您需要如何分配图像以使此代码起作用有很好的限制。
例如,假设你的直方图函数与上面所写的相同,那么这些图像分配策略都不会起作用:(为简洁起见,我使用char
代替unsigned char
。)< / p>
char image [width * height]; // Obvious; "char[]" != "char **"
char * image = new char [width * height]; // "char*" != "char **"
char image [height][width]; // Most surprisingly, this won't work either.
第三种情况不起作用的原因很难简单解释。可以这么说,像这样的2D数组不会隐含地衰减成指向指针的指针,如果确实如此,那将毫无意义。与你在某些书中读到或听到某些人的看法相反,在C / C ++中,数组和指针不是是同一件事!
无论如何,为了使直方图功能正常工作,您必须像这样分配图像:
char** image = new char* [height];
for (int i = 0; i < height; ++i)
image[i] = new char [width];
现在您可以填写图片,例如:
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
image[i][j] = rand() % 256; // Or whatever...
在像这样分配的图像上,你可以调用你的直方图功能,它会起作用。完成此图像后,您必须像这样释放它:
for (int i = 0; i < height; ++i)
delete[] image[i];
delete[] image;
目前,分配就足够了。我稍后再回来。
除了上述内容之外,注意图像上的迭代顺序至关重要。你编写它的方式,你在外面迭代你的列,你的内循环遍历行。大多数(所有?)图像文件格式和我见过的许多(大多数?)图像处理应用程序反过来。我上面显示的内存分配也假设第一个索引用于行,第二个索引用于列。我建议你这样做,除非你有充分的理由不这样做。
无论您为图片选择哪种布局(推荐的行专业或当前专栏专业版),都应该始终牢记并注意这一点。
现在,按照我推荐的方式分配和访问图像并计算直方图。
我建议你像这样分配和释放图像:
// Allocate:
char * image = new char [height * width];
// Free:
delete[] image;
就是这样;没有讨厌的(de)分配循环,每个图像都是一个连续的内存块。当您想要访问行i
和列j
时(注意哪个是哪个),您可以这样做:
image[i * width + j] = 42;
char x = image[i * width + j];
你可以像这样计算直方图:
void histogram (
unsigned char * image, int height, int width,
// Note that the elements here are pixel-counts, not colors!
vector<unsigned> & histogram
) {
// Make sure histogram has enough room; you can do this outside as well.
if (histogram.size() < 256)
histogram.resize (256, 0);
int pixels = height * width;
for (int i = 0; i < pixels; ++i)
histogram[image[i]]++;
}
我已经删除了打印代码,无论如何都不应该存在。请注意,我使用了一个循环来遍历整个图像;这是分配1D阵列的另一个优点。此外,对于此特定功能,您的图像是行主要还是列主要无关紧要,因为我们通过像素的顺序无关紧要;只重要的是我们通过所有像素,而不是更多。
更新:问题更新后,我认为上述所有讨论都没有实际意义,尽管如此!我相信问题可能出在直方图矢量的声明中。它应该是unsigned int
s的向量,而不是单个字节。您的问题似乎是,当您简化代码并仅增加一个元素时,向量元素的值似乎保持为零,并且与运行实际代码时所需的值不同。好吧,这可能是数字环绕的症状。如果图像中的像素数是256的倍数(例如32x32或1024x1024图像),那么它们的数量之和将是0 mod 256是很自然的。
我在原来的答案中已经提到了这一点。如果您阅读我对histogram
函数的实现,您会在签名中看到我已将我的向量声明为vector<unsigned>
并在其上面添加了一条注释,表示此victor计算像素,因此其数据类型应该是合适的。
我想我应该让它更大胆更清晰!我希望这能解决你的问题。