我想这是一个很简单的问题(我来自 Java),但我不知道它是如何工作的。
我只是想将 vector 元素加一。这样做的原因是,我想根据图像值计算直方图。但是无论我尝试什么,我都可以完成为 vector 分配一个值。但不要将其增加一!
这是我的直方图函数:
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)与应有的不同。直方图的值也与图形程序中的不同——即使图像值完全相同!这就是为什么我研究了该函数并发现如果我将直方图设置为零然后尝试增加一个元素,没有任何 react !这是上面的注释代码:
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!直方图数组[1] = 2;工作正常。还有 histogramArray[(int)image[i][j]]++;似乎计算了一些东西,但正如我所说,我认为它计算错误。
我非常感谢任何帮助!我使用二维数组的原因仅仅是因为它被要求。我也更喜欢 1D 版本,因为它更简单!
最佳答案
你看,你代码中的当前问题是 不是 增加一个值而不是分配给它;这是您索引图像的方式。您编写histogram
的方式函数和图像访问部分对您需要如何分配图像以使此代码正常工作提出了非常严格的限制。
例如,假设您的直方图函数如您在上面编写的那样,这些图像分配策略都不起作用:(为简洁起见,我使用了 char
而不是 unsigned char
。)
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;
而已;没有讨厌的(取消)分配循环,每个图像都是一个连续的内存块。当你想访问行
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]]++;
}
我已经消除了打印代码,无论如何它都不应该存在。请注意,我使用了一个循环来遍历整个图像;这是分配一维数组的另一个优点。此外,对于这个特定功能,您的图像是行优先还是列优先都无关紧要,因为我们通过像素的顺序无关紧要;重要的是我们遍历所有像素,仅此而已。
更新 : 问题更新后,我认为以上所有讨论都没有实际意义!我相信问题可能出在直方图 vector 的声明中。它应该是
unsigned int
的 vector s,不是单个字节。您的问题似乎是,当您简化代码并仅增加一个元素时, vector 元素的值似乎保持为零,并且与运行实际代码时所需的值不同。好吧,这可能是数字环绕的症状。如果图像中的像素数是 256 的倍数(例如 32x32 或 1024x1024 图像),那么它们的数量之和自然会是 0 mod 256。我已经在我的原始答案中提到了这一点。如果你阅读了我的
histogram
的实现函数,您在签名中看到我已将 vector 声明为 vector<unsigned>
并在上面写了一条评论,说这个胜利者计算像素,所以它的数据类型应该是合适的。我想我应该让它更大胆更清晰!我希望这能解决你的问题。
关于c++ - 将 1 添加到 vector <unsigned char> 值 - C++ 中的直方图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22601712/