图像基本操作
0. 打开图片
string imagename = "lena.jpg"; //绝对地址
Mat img = imread(imagename); if(img.empty()) { return -1; } imgShow(imagename, img);
像素数据属性:
一幅图片可以用 a[height][width][channels]表示,Mat类似于映射到一维数组,其中每个像素点的rgb分量按照bgr的顺序连续存放。
像素点数:
int tot = img.size().area() * img.channels();
高和宽:
int height = img.size().height; int width = img.size().width;
每个像素点类型为uchar(unsigned char):
img.data[i];
1. rgb转为灰度图像
灰度:YUV的颜色空间中,Y的分量的物理意义是点的亮度,由该值反映亮度等级,用亮度值表示灰度
Y=0.3R+0.59G+0.11B
简单的方法:用Y替换rgb分量
for (int i = 0; i < tot; i+=3) {
unsigned int temp = (unsigned int)(0.3*img.data[i+2] + 0.59*img.data[i+1] + 0.11*img.data[i]);
img.data[i] = img.data[i+1] = img.data[i+2] = temp;
}

2. 直方图均衡化
直方图均衡化使用的是频率累加曲线进行映射(区别于直方图规定化/直方图匹配)
简单方法:计算累加频率曲线,分别对rgb三个通道进行均衡化
单通道均衡化:
void equalization(Mat &img, int tot, int offSet)
{
int cnt[256];
int cdfMin = tot;
memset(cnt, 0, sizeof(cnt));
for (int i = 0; i < tot; i += 3) {
++cnt[ img.data[i+offSet] ];
}
for (int i = 1; i < 256; ++i) {
cnt[i] += cnt[i-1];
}
for (int i = 0; i < 256; ++i) {
if (0!=cnt[i] && cdfMin>cnt[i]) cdfMin = cnt[i];
}
for (int i = 0; i < tot; i += 3) {
unsigned int temp = (unsigned int)((cnt[ img.data[i+offSet] ]-cdfMin)*255.0 / (img.size().area()-cdfMin));
img.data[i+offSet] = temp;
}
}
rgb三通道均衡化:
equalization(img, tot, 0); equalization(img, tot, 1); equalization(img, tot, 2);

3. 简单马赛克
简单方法:选取固定大小的矩形区域,用其中某一个点值代替区域内所有像素值
len为矩形宽度,矩形大小为len*len
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
int k = i*width*3+j*3;
int t = (i-i%len)*width*3+(j-j%len)*3;
img.data[k] = img.data[t];
img.data[k+1] = img.data[t+1];
img.data[k+2] = img.data[t+2];
}
}

4. 反色变换:y = 255 - x;
5. gama变换:y = c * x^gama
注意满足 L-1 = c * (L-1)^gama, L=256
用颜色表的方法可能会稍微快点。
for (int i = 0; i < tot; i+=3) {
int temp = (int) (c * pow(img.data[i], gama));
img.data[i] = img.data[i+1] = img.data[i+2] = temp;
}
gama = 0.2, 1, 3.0分别如下:




浙公网安备 33010602011771号