首页 > 编程知识 正文

opencv修改像素值,opencv指定区域修改像素

时间:2023-05-05 20:13:51 阅读:228854 作者:1466

1、matlab获取彩色图像像素值的方法

img=imread('test.jpg');

img1=img(:,:,1);
img2=img(:,:,2);
img3=img(:,:,3);

三通道排序分别对应彩色图像的rgb三通道

2、opencv中获取图像像素的方法

方法一:

IplImage *img = cvLoadImage("Lena.jpg", 0);

CvScalar pixel;
for (int i = 0; i < img->height; ++i)
{
for (int j = 0; j < img->width; ++j)
{
//获得像素的RGB值并显示

pixel = cvGet2D(img, i, j);
printf("B=%f,G=%f,R=%ft", pixel.val[0], pixel.val[1], pixel.val[2]);
//修改各点的值
pixel.val[0] = 0; // B分量
pixel.val[1] = 0; // G分量
pixel.val[2] = 0; // R分量
cvSet2D(img, i, j, pixel);
}
}

注意内存中存储顺序是BGR

方法二:

for (int i = 0; i < img->height; ++i)
{
for (int j = 0; j < img->width; ++j)
{

int b = CV_IMAGE_ELEM(paintx, uchar, y1, x1 * 3);

int g = CV_IMAGE_ELEM(paintx, uchar, y1, x1 * 3+1);

int r= CV_IMAGE_ELEM(paintx, uchar, y1, x1 * 3+2);
}

}

假设灰度图像image,存取其i行j列的象素可以这样:CV_IMAGE_ELEM(image, uchar,y, x)

如果是彩色图像就是
CV_IMAGE_ELEM(image, uchar,y, 3*x)
CV_IMAGE_ELEM(image, uchar,y, 3*x+1)
CV_IMAGE_ELEM(image, uchar,y, 3*x+2)

 

CV_IMAGE_ELEM是一个宏,

#define CV_IMAGE_ELEM( image, elemtype, row, col )
(((elemtype*)((image)->imageData + (image)->widthStep*(row)))[(col)])

#define CV_MAT_ELEM( mat, elemtype, row, col )
(*(elemtype*)CV_MAT_ELEM_PTR_FAST( mat, row, col, sizeof(elemtype)))

呵呵,我一直把它当一个函数用,其实本质也没有什么区别的

但要想正确的得到图像的坐标为(x,y)点的像素值,是应该这样写CV_IMAGE_ELEM(Image, uchar, y, x)

要注意像素点的坐标xy和行列值的顺序是相反的(可以仔细思考为什么)

我刚开始一直写成CV_IMAGE_ELEM(Image, uchar, x, y),结果有时候就造成了访问image越界,从而报错,花了好长时间才捣鼓出来,

不过将IMAGE的数据按照原来的样子复制到mat中可以这么写:
CV_IMAGE_ELEM(pImage, uchar, i, j) = CV_MAT_ELEM(*mat, uchar, i, j)

不用改变顺序

总之,当应用这个宏是如果老报错,就试试换个顺序,或者检查访问的地址是否越界



方法三:

对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

((uchar *)(img->imageData + i*img->widthStep))[j]=111;

对于多通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +0]=111;//B

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +1]=112;//G

((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels +2]=113;//R

对于多通道浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111;//B

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112;//G

((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113;//R

3 ((uchar*)(Img1->imageData + Img1->widthStep*pt.y))[pt.x]的具体含义:
(1)这里img1->imagedata指的图像第一行的首地址,pt.y是指图像的height(图像高像素数即行数),y乘以img->widthstep(排列的图像行大小)即首地址加上行数乘以每行总数,得到第y行的首地址。widthstep是指图像每行所占的字节数,主要要和width区别,width是指每行所含的像素个数,但是一个像素也可能占一个字节,也可能占三个字节或者四个。imagedata是指向存储图像像素值数组的指针,内容是这个数组的首地址,pt.y指的是像素点的行坐标,所以Img->imageData + Img->widthStep*pt.y便是该像素点所在行的首地址,然后再加上该像素点所在的列,即pt.x,就得到了该像素点的地址,所以那句代码也可以写成

((uchar*)(Img1->imageData + Img1->widthStep*pt.y+pt.x)),

都是指该像素点的像素值,至于强制类型转换,是因为会产生一些负值,而像素值是不能为负的。

(2)widthStep表示存储一行像素需要的字节数。
widthStep必须是4的倍数,如果8U图像宽度为3,那么widthStep是4,加一个字节补齐。这个图像的一行需要4个字节,只使用前3个,最后一个空在那儿不用。也就是一个宽3高3的图像的imageData数据大小为4*3=12字节。如果32F的图像,那么widthStep=width*4。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。