前言
阅读老旧的opencv的代码,发现了这一句话:
IplImage *img = w->img;
cout<< ((uchar(*))(img->imageData + (img->widthStep)[100]))[5] <<endl;
百度imageData,发现只是很模糊的描述“imageData指向存储图像数据的一块数据区”、“排列的图像行大小”。
我们都知道,一张图是由无数个像素点构成的,每个像素点的像素值都不同所以我们看到的图片才具有丰富的颜色。
imageData就是一个指针,指向某张图片像素值数据的首地址。
作用
imageData既然和像素值有关,那很多涉及到像素值的操作就离不开它。
举例
当我们想要改变一张分辨率为(100,100)图片上某一点A(70,20)的颜色是黑色怎么办?(图片为img)
思路
首先要在imageData中找到像素点A,然后再更改它的像素值。
(1) 先找到存放img图片所有像素点的像素值信息的地址。
即img->imageData
(2) 由于点A在“第70行”,所以可以用img->widthStep追踪到A点所在行像素点的像素值集合。
img->imageData + (img->widthStep)*70
(3) 又由于点A在“第20列”,所以最终有下式定位A点:
(img->imageData + (img->widthStep)*70)[20]
[ widthStep和width的不同]
[ widthStep和width的不同] width为该图片的宽度的分辨率,而由于图片有不同的深度(比如有的是单通道图,有的是RGB三通道图), 每张图片像素点的像素值的数值大小范围也不同(所需要的字节不同),所以widthStep就是表示某图片的每行像素点的像素值所需要的字节大小。widthStep一般是4的倍数。 例如本题(单通道图),width值为100,而widthStep是100. |
(4)让该点变白(白色的像素值为255)
((uchar*)(img->imageData + (img->widthStep) * 70))[20] = 255;
代码
#include "stdafx.h"
#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
int main()
{
//IPL_DEPTH_8U决定了这张图是单通道图
IplImage *img = cvCreateImage(cvSize(100, 100), IPL_DEPTH_8U, 1);//cvLoadImage("D:\\hh\\left.jpg");
cout << "width:" << img->width << endl;
cout << "widthStep:" << img->widthStep << endl;
((uchar*)(img->imageData + (img->widthStep) * 70))[20] = 255;
cvShowImage("window", img);
waitKey(0);
}