如何通过Vimba C API获取图像灰度值并计算像素质心
Vimba C API灰度图像质心计算问题
我正在使用Vimba C语言API,基于官方的SynchronousGrab示例修改代码,首次使用Visual Studio开发。需求是在相机采集的深色灰度图中,找到较亮像素云的质心,目前在适配更大尺寸图像时遇到坐标计算错误的问题。
相关代码与定义
函数内变量声明
VmbError_t SynchronousGrab( const char* pCameraID, const char* pFileName, int threshold ) { VmbFrame_t frame; // The frame we capture VmbUint32_t j = 0; //CUSTOM VmbUint32_t k = 0; //CUSTOM unsigned char* CurSrc = 0; //CUSTOM int arraysize = 0; //CUSTOM float* coordY = 0; //CUSTOM float* coordX = 0; //CUSTOM float* intensity = 0; //CUSTOM float centroid_x = -1; //CUSTOM float centroid_y = -1; //CUSTOM
VmbFrame_t结构体定义
typedef struct { //----- In ----- void* buffer; // Comprises image and ancillary data VmbUint32_t bufferSize; // Size of the data buffer void* context[4]; // 4 void pointers that can be employed by the user (e.g. for storing handles) //----- Out ----- VmbFrameStatus_t receiveStatus; // Resulting status of the receive operation VmbFrameFlags_t receiveFlags; // Flags indicating which additional frame information is available VmbUint32_t imageSize; // Size of the image data inside the data buffer VmbUint32_t ancillarySize; // Size of the ancillary data inside the data buffer VmbPixelFormat_t pixelFormat; // Pixel format of the image VmbUint32_t width; // Width of an image VmbUint32_t height; // Height of an image VmbUint32_t offsetX; // Horizontal offset of an image VmbUint32_t offsetY; // Vertical offset of an image VmbUint64_t frameID; // Unique ID of this frame in this stream VmbUint64_t timestamp; // Timestamp set by the camera } VmbFrame_t;
自定义像素分析代码
err = VmbCaptureFrameWait( cameraHandle, &frame, nTimeout ); if ( VmbErrorSuccess == err ) //Existing SynchronousGrab code { CurSrc = (unsigned char*)frame.buffer; for (k = 0; k < frame.height; k++) { for (j = 0; j < frame.width; j++) { if (*(CurSrc+k * frame.width + j) >= threshold) { coordY = realloc(coordY, ++arraysize * sizeof(*coordY)); coordX = realloc(coordX, arraysize * sizeof(*coordX)); intensity = realloc(intensity, arraysize * sizeof(*intensity)); coordY[arraysize - 1] = k * (*(CurSrc + k * frame.width + j)); coordX[arraysize - 1] = j * (*(CurSrc + k * frame.width + j)); intensity[arraysize - 1] = (*(CurSrc + k * frame.width + j)); } } } if (arraysize != 0) { centroid_x = getSum(coordX, arraysize) / getSum(intensity, arraysize); centroid_y = getSum(coordY, arraysize) / getSum(intensity, arraysize); printf("Centroid is in (%.1f,%.1f)\n", centroid_x, centroid_y); free(coordX); free(coordY); free(intensity); arraysize = 0; } if ( VmbFrameStatusComplete == frame.receiveStatus ) //Existing SynchronousGrab code
自定义getSum函数
int getSum(float* head, int size) { //CUSTOM FUNCTION int i; int sum = 0; for (i = 0; i < size; i++) { sum = sum + head[i]; } return sum; }
问题现象
- 原算法在固定1440×1080尺寸图像上测试可行,但适配更大尺寸图像后,质心坐标计算错误。
- 最初误用固定值1440代替
frame.width,修改后首次运行时centroid_y为负数(但赋值为两个正数的乘积),后续运行转为正数,但坐标误差达1900像素左右。 - 质心坐标存在小幅波动,怀疑由相机或工作台振动导致,但主要问题是坐标偏移错误。
怀疑点与补充信息
- 怀疑
frame.buffer并非指向长度为frame.width * frame.height的灰度像素数组,但因相机设置访问受限,暂时无法采用暴力内存排查方案。 - 事后发现代码位置错误:质心计算逻辑应该放在
VmbFrameStatusComplete == frame.receiveStatus的判断分支内,当前代码可能读取了未完全接收的图像数据。
内容的提问来源于stack exchange,提问作者ATSlooking4things
相关产品推荐
相关产品推荐

