转载自:http://blog.sina.com.cn/s/blog_794d61e80102w3zb.html
重点代码块:
int data_max = 0,data_min = 255;//预设灰度值
int nl = image.rows; //计算图像的行数
int nc = image.cols * image.channels();//计算图像的列数*通道数[注释1]
if(image.isContinuous()) //判断图像在内存中是否连续存储[注释2]
{
nc = nc * nl;
nl = 1;
}
int i,j;
uchar *data; //定义访问指针
for(j = 0; j < nl; j ++)
{
data = image.ptr<uchar>(j);//指针指向image的第j行,image如果连续存储,j=1
for(i = 0; i < nc; i ++)
{
if(data[i] > data_max) data_max = data[i];
if(data[i] < data_min) data_min = data[i];
}
}
注释1:图像是一个二维矩阵,按照行列访问,如果是彩色三通道的图像,则可以看作类似魔方的三位矩阵,
还是按照行列访问,但是每一列会有三个通道数的像素值BGR。
此处把通道数算进去列数里面,就可以每个像素的三个通道都遍历赋值,把三维矩阵看作二维矩阵。
注释2:当图像在内存中是连续储存的,则可以把行列数归并,
把二维矩阵nl行*nc列看作一维矩阵1行*(nl*nc)列。
实战完整C++代码:
C/C++ Demo: 把灰度级由其原范围线性地拉伸至整个灰度级范围。
//通用
#include <iostream>
#include <stdio.h>
//图像操作
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace :: std;
using namespace :: cv;
int main()
{
//图像读取
Mat image = imread("Fig0310.tif");
//判断图像读取是否有问题
if(!image.data)
{
cout << "image read is error!" << endl;
return 0;
}
//图像基本信息输出
cout << "image Info:Height:" << image.size().height << " Width:" << image.size().width << endl;
//原始图像显示
namedWindow("Original Image");
imshow("Original Image", image);
imwrite("original.jpg", image);
//处理图像
int data_max = 0,data_min = 255;
int nl = image.rows;
int nc = image.cols * image.channels();
if(image.isContinuous())
{
nc = nc * nl;
nl = 1;
}
int i,j;
uchar *data;
for(j = 0; j < nl; j ++)
{
data = image.ptr<uchar>(j);
for(i = 0; i < nc; i ++)
{
if(data[i] > data_max) data_max = data[i];
if(data[i] < data_min) data_min = data[i];
}
}
cout << "data_max:" << data_max << " data_min:" << data_min << endl;
int temp = data_max - data_min;
for(j = 0; j < nl; j ++)
{
data = image.ptr<uchar>(j);
for(i = 0; i < nc; i ++)
{
data[i] = (data[i] - data_min) * 255 / temp;
}
}
//显示图像
namedWindow("Process Image");
imshow("Process Image", image);
//保存图像
imwrite("result.JPG", image);
waitKey(0);
return 0;
}