opencv——访问图像元素(imagedata widthstep)

本文详细介绍了如何在OpenCV中处理图像和矩阵元素,包括访问图像像素、调整图像亮度、加载显示图像等基本操作,同时也提供了处理矩阵元素的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.sina.com.cn/s/blog_759803690101gtpx.html

怎么访问图像元素
(坐标起点相对于图像原点 image origin 从 开始,或者是左上角 (img->origin=IPL_ORIGIN_TL) 或者是左下角 (img->origin=IPL_ORIGIN_BL) 

假设有 8-bit 1-通道的图像 (IplImage* img): 
I(x,y) ((uchar*)(img->imageData img->widthStep*y))[x]

假设有 8-bit 3-通道的图像 (IplImage* img): 
I(x,y)blue ((uchar*)(img->imageData img->widthStep*y))[x*3]
I(x,y)green ((uchar*)(img->imageData img->widthStep*y))[x*3+1]
I(x,y)red ((uchar*)(img->imageData img->widthStep*y))[x*3+2]

如果增加点 (100,100) 的亮度 30 ,那么可以: 
CvPoint pt {100,100};
((uchar*)(img->imageData img->widthStep*pt.y))[pt.x*3] += 30;
((uchar*)(img->imageData img->widthStep*pt.y))[pt.x*3+1] += 30;
((uchar*)(img->imageData img->widthStep*pt.y))[pt.x*3+2] += 30;

或者更有效的 
CvPoint pt {100,100};
uchar* temp_ptr &((uchar*)(img->imageData img->widthStep*pt.y))[x*3];
temp_ptr[0] += 30;
temp_ptr[1] += 30;
temp_ptr[2] += 30;

假设有 32-bit 浮点数, 1-通道 图像 (IplImage* img): 
I(x,y) ((float*)(img->imageData img->widthStep*y))[x]

现在,通用方法:假设有 N-通道,类型为 的图像:
I(x,y)c ((T*)(img->imageData img->widthStep*y))[x*N c]
或者你可使用宏 CV_IMAGE_ELEM( image_header, elemtype, y, x_Nc )
I(x,y)c CV_IMAGE_ELEM( img, T, y, x*N )

也有针对各种图像(包括 4-通道)和矩阵的函数(cvGet2D, cvSet2D), 但是它们都很慢. 
--------------------------------------------------------------------------------

如何访问矩阵元素?
方法是类似的 (都是针对 起点的列和行) 

设有 32-bit 浮点数的实数矩阵 (CvMat* mat): 
M(i,j) ((float*)(mat->data.ptr mat->step*i))[j]

设有 64-bit 浮点数的复数矩阵 (CvMat* mat): 
Re M(i,j) ((double*)(mat->data.ptr mat->step*i))[j*2]
Im M(i,j) ((double*)(mat->data.ptr mat->step*i))[j*2+1]

设有单通道矩阵,有宏 CV_MAT_ELEM( matrix, elemtype, row, col ), 例如对 32-bit 浮点数的实数矩阵
M(i,j) CV_MAT_ELEM( mat, float, i, ),
假如初始化 3x3 单位阵:
CV_MAT_ELEM( mat, float, 0, 1.f;
CV_MAT_ELEM( mat, float, 0, 0.f;
CV_MAT_ELEM( mat, float, 0, 0.f;
CV_MAT_ELEM( mat, float, 1, 0.f;
CV_MAT_ELEM( mat, float, 1, 1.f;
CV_MAT_ELEM( mat, float, 1, 0.f;
CV_MAT_ELEM( mat, float, 2, 0.f;
CV_MAT_ELEM( mat, float, 2, 0.f;
CV_MAT_ELEM( mat, float, 2, 1.f;


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

如何在 OpenCV 中处理我自己的数据
设你有 300x200 32-bit 浮点数 image/array, 也就是对一个有 60000 个元素的数组. 

int cols 300, rows 200;
float* myarr new float[rows*cols];

// step 1) initializing CvMat header
CvMat mat cvMat( rows, cols,
                   CV_32FC1, // 32-bit floating-point, single channel type
                   myarr // user data pointer (no data is copied)
                   );
// step 2) using cv functions, e.g. calculating l2 (Frobenius) norm
double norm cvNorm( &mat, 0, CV_L2 );

...
delete myarr;

其它情况在参考手册中有描述.见 cvCreateMatHeader, cvInitMatHeader, cvCreateImageHeader, cvSetData etc. 
--------------------------------------------------------------------------------

如何加载和显示图像

#include "cv.h"
#include "highgui.h"

int main( int argc, char** argv )
{
    IplImage* img;
    if( argc == && (img cvLoadImage( argv[1], 1)) != )
    {
        cvNamedWindow( "Image view", );
        cvShowImage( "Image view", img );
        cvWaitKey(0); // very important, contains event processing loop inside
        cvDestroyWindow( "Image view" );
        cvReleaseImage( &img );
        return 0;
    }
    return -1;
}

 

void cvLaplace (IplImage* src, IplImage* dst, int apertureSize=3);
void cvSobel (IplImage* src, IplImage* dst, int dx, int dy, int apertureSize=3);
void cvCanny (IplImage* img, IplImage* edges, double lowThresh, double highThresh, int apertureSize=3);

void cvPreCornerDetect (IplImage* img, IplImage* corners, Int apertureSize);
void cvCornerEigenValsAndVecs (IplImage* img, IplImage* eigenvv, int blockSize, int apertureSize=3);
void cvCornerMinEigenVal (IplImage* img, IplImage* eigenvv, int blockSize, int apertureSize=3);
void cvGoodFeaturesToTrack (IplImage* image, IplImage* eigImage, IplImage* tempImage, CvPoint2D32f* corners, int* cornerCount, double qualityLevel,double minDistance);
//对已经粗检测出的角点进行亚像素精准定位
void cvFindCornerSubPix (IplImage* img, CvPoint2D32f* corners, int count,CvSize win, CvSize zeroZone, CvTermCriteria criteria);

//金字塔分解与重构
void cvPyrDown (IplImage* src, IplImage* dst, IplFilter filter=IPL_GAUSSIAN_5x5);
void cvPyrUp (IplImage* src, IplImage* dst, IplFilter filter=IPL_GAUSSIAN_5x5);

void cvThreshold (IplImage* src, IplImage* dst, float thresh, float maxvalue,CvThreshType type);

void cvProject3D CvPoint3D32f* points3D, int count, CvPoint2D32f* points2D,int xindx, int yindx);

void cvFindFundamentalMatrix (int* points1, int* points2, int numpoints, int method, CvMatrix3* matrix);

//很好用的平滑函数
void cvSmooth( const CvArr* src, CvArr* dst,int smoothtype=CV_GAUSSIAN,int param1=3, int param2=0, double param3=0 );
CV_BLUR_NO_SCALE CV_BLUR CV_GAUSSIAN CV_MEDIAN CV_BILATERAL

其他辅助函数:
void cvPutText( CvArr* img, const char* text, CvPoint org, const CvFont* font, CvScalar color );

cvCvtColor(image, gray, CV_BGR2GRAY);//彩色图像灰度化

cvCvtPlaneToPix( planes[0], planes[1], planes[2], 0, currentimage);
cvSplit(colorimage,plane[0],plane[1],plane[2],0);

### OpenCV 的 C 语言使用指南 尽管现代 OpenCV 更倾向于支持 C++ 和 Python 接口,但在某些场景下仍然可以使用其传统的 C 风格接口。以下是关于如何查找和学习 OpenCV 中基于 C 语言的相关资源的信息。 #### 关于文件命名与模块结构 OpenCV 的核心库(`cv`, `cvaux`)确实是由 C 和 C++ 编写而成[^1]。这意味着部分功能可以通过纯 C 接口调用。然而需要注意的是,在较新的版本中,官方更推荐使用 C++ 或者更高层的语言绑定来实现图像处理操作。如果坚持采用 C 风格,则需特别关注旧版文档中的 API 定义以及对应的头文件引入方式。 #### 头文件包含路径 当利用 C 接口开发程序时,通常需要显式导入如下形式的基础头文件: ```c #include <opencv/cv.h> #include <opencv/highgui.h> ``` 上述两行分别用于加载基础算法库和支持图形界面交互的功能集合[^3]。不过请注意,自 OpenCV 3.x 版本之后,许多传统意义上的独立组件已经被重新组织进了统一的命名空间之下(`cv`),这可能会影响到具体函数名称前缀的选择——比如从全局作用域转移到特定子模块内部。 #### 函数调用示例 下面给出一段简单的例子展示怎样通过原始C方法创建矩阵对象并执行基本运算: ```c IplImage* img = cvCreateImage(cvSize(640,480), IPL_DEPTH_8U, 3); CvScalar s; for(int i=0;i<img->height;i++) { uchar *data=(uchar*)(img->imageData+i*img->widthStep); for (int j=0;j<img->width*img->nChannels;j+=img->nChannels){ data[j]=255;//red channel set to max value. data[j+1]=0 ;//green channel zeroed out . data[j+2]=0 ;//blue channel also cleared .. } } s=cvSum(img);printf("%f %f %f\n",s.val[0],s.val[1],s.val[2]); cvReleaseImage(&img ); ``` 此代码片段展示了如何手动分配内存给图片数据缓冲区,并逐像素设置颜色值最后计算整幅图象亮度总合. #### 调试技巧补充 针对可能出现的各种运行期错误情况,建议参考专门讨论C/C++环境下调试技术的文章进一步提升解决问题的能力[^5]. 此外考虑到实际项目往往涉及多线程并发控制等因素影响最终表现效果,深入理解目标平台特性同样重要. #### 总结 虽然当前主流趋势偏向高级抽象层次封装后的简便语法表达形式,但对于追求极致性能优化或者兼容遗留系统的场合来说掌握底层细节依然很有价值。希望以上介绍能够帮助您找到适合自己的学习方向!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值