使用vImageHistogramCalculation计算图像的直方图

4
我正在尝试使用vImage的vImageHistogramCalculation_ARGBFFFF计算图像的直方图,但是我收到了一个类型为kvImageNullPointerArgument(错误代码为-21772)的vImage_Error

这是我的代码:

- (void)histogramForImage:(UIImage *)image {

    //setup inBuffer
    vImage_Buffer inBuffer;

    //Get CGImage from UIImage
    CGImageRef img = image.CGImage;

    //create vImage_Buffer with data from CGImageRef
    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);

    //The next three lines set up the inBuffer object
    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);

    //This sets the pointer to the data for the inBuffer object
    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);

    //Prepare the parameters to pass to vImageHistogramCalculation_ARGBFFFF
    vImagePixelCount *histogram[4] = {0};
    unsigned int histogram_entries = 4;
    Pixel_F minVal = 0;
    Pixel_F maxVal = 255;
    vImage_Flags flags = kvImageNoFlags;

    vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer,
                                                             histogram,
                                                             histogram_entries,
                                                             minVal,
                                                             maxVal,
                                                             flags);
    if (error) {
        NSLog(@"error %ld", error);
    }

    //clean up
    CGDataProviderRelease(inProvider);
}

我猜测这与我的直方图参数有关,根据文档,它应该是“指向四个直方图数组的指针”。我声明正确吗?
谢谢。

问题在这里:vImagePixelCount *histogram[4] = {0}; 你正在初始化一个包含直方图结果的四个空指针的数组。如果没有其他人先回答,我稍后会提供更详细的答案。 - Stephen Canon
嘿@StephenCanon,看起来除了你之外没有其他人处理它。如果你能提供上面评论的更多细节就太好了! - Eric
@Eric...我尝试了Stephen的逻辑,但在两种情况下都出现了EXC_BAD_Access错误。你能建议我可能出了什么问题吗? - Imran
1个回答

5
麻烦的是,你没有为计算得出的直方图分配空间。如果只在本地使用直方图,可以将它们放在堆栈中,像这样[请注意我使用了八个箱子而不是四个,以使示例更清晰]:
// create an array of four histograms with eight entries each.
vImagePixelCount histogram[4][8] = {{0}};
// vImageHistogramCalculation requires an array of pointers to the histograms.
vImagePixelCount *histogramPointers[4] = { &histogram[0][0], &histogram[1][0], &histogram[2][0], &histogram[3][0] };
vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer, histogramPointers, 8, 0, 255, kvImageNoFlags);
// You can now access bin j of the histogram for channel i as histogram[i][j].
// The storage for the histogram will be cleaned up when execution leaves the
// current lexical block.

如果您需要在函数范围之外保留直方图,您需要在堆上为它们分配空间:
vImagePixelCount *histogram[4];
unsigned int histogramEntries = 8;
histogram[0] = malloc(4*histogramEntries*sizeof histogram[0][0]);
if (!histogram[0]) { // handle error however is appropriate }
for (int i=1; i<4; ++i) { histogram[i] = &histogram[0][i*histogramEntries]; }
vImage_Error error = vImageHistogramCalculation_ARGBFFFF(&inBuffer, histogram, 8, 0, 255, kvImageNoFlags);
// You can now access bin j of the histogram for channel i as histogram[i][j].
// Eventually you will need to free(histogram[0]) to release the storage.

希望这能帮到你。

嘿,Stephen,谢谢你的回答。不过,我在你的第一段代码中遇到了一些问题。在我声明“histogramPointers”的那一行上,我得到了一个警告,它说:“使用'type vImagePixelCount (*)[8]'的表达式初始化不兼容的指针类型'vImagePixelCount *'(也称为'unsigned long *')”,并且当调用vImageHistogramCalculation_ARGBFFFF时,应用程序会崩溃并显示EXC_BAD_ACCESS。有什么想法吗? - Eric
1
抱歉,看起来我不小心发布了早期版本的代码;现在请再试一次。 - Stephen Canon
谢谢,现在可以正常运行了。但是结果让我有点困惑。所有四个通道都是这样的:([0] = 727040, [1] = 0, [2] = 0, [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0)... 你有什么想法吗? - Eric
1
考虑到图像格式为浮点型,很可能像素值已经归一化到[0,1]范围内,因此它们都会落入第一个区间(当min=0且max=255时,该区间覆盖[0,31.875))。你可能想要使用min=0.0,max=1.0。 - Stephen Canon
histogramEntries通常是一个较大的数字,例如256。它并不表示直方图的数量,而是每个直方图中的条目数。此外,您的图像数据中是否有任何内容,或者是否初始化为全零? - Ian Ollmann
@StephenCanon... 我尝试了上面的两个代码,但出现了EXC_BAD_Access错误...你能告诉我可能出了什么问题吗? - Imran

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接