double t1 = (double)getTickCount(); //计时开始
... //需要计时的程序
double t2 = (double)getTickCount(); //计时结束
cout<<"time:"<<(t2-t1)/(getTickFrequency())<<endl; //时间输出
例1:
#include
#include
#include
using namespace std;
using namespace cv;
int main(void)
{
// 计时开始
double t1 = (double)getTickCount();
Mat R = Mat(5, 5, CV_8UC3); //用随机值填充一个矩阵
randu(R, Scalar::all(0), Scalar::all(255));
cout << "R (default) = " << endl << R << endl << endl;
// 计时结束
double t2 = (double)getTickCount();
// 时间输出
cout << "运行时间:" << (t2 - t1) / (getTickFrequency()) << "秒" << endl;
return 0;
}
执行结果:
R (default) =
[ 91, 2, 79, 179, 52, 205, 236, 8, 181, 239, 26, 248, 207, 218, 45;
183, 158, 101, 102, 18, 118, 68, 210, 139, 198, 207, 211, 181, 162, 197;
191, 196, 40, 7, 243, 230, 45, 6, 48, 173, 242, 125, 175, 90, 63;
90, 22, 112, 221, 167, 224, 113, 208, 123, 214, 35, 229, 6, 143, 138;
98, 81, 118, 187, 167, 140, 218, 178, 23, 43, 133, 154, 150, 76, 101]
运行时间:0.0028112秒
在图像处理中,很常见的是要将所有给定的图像值修改为其他值。OpenCV提供了修改图像值的功能,无需编写图像的扫描逻辑。我们使用核心模块的cv :: LUT()函数。首先我们构建一个Mat类型的查找表:
Mat lookUpTable(1, 256, CV_8U);
uchar* p = lookUpTable.ptr();
for( int i = 0; i < 256; ++i)
p[i] = table[i];
最后调用函数(我是我们的输入图像,J是输出的一个):
LUT(I,lookUpTable,J);
1. opencv 2中的LUT函数为
void LUT(InputArray src, InputArray lut, OutputArray dst,int interpolation);
2. opencv3里面的LUT函数
void LUT(InputArray src, InputArray lut, OutputArray dst);
和2一样,不过没有了interpolation这个参数。
#include
using namespace cv;
int main()
{
//查找表,数组的下标对应图片里面的灰度值
//例如lutData[20]=0;表示灰度为20的像素其对应的值0.
//可能这样说的不清楚仔细看下代码就清楚了。
uchar lutData[256];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
lutData[i] = 0; //0-100灰度的像素灰度变成0
if (i > 100 && i <= 200)
lutData[i] = 100; //101-200的像素灰度变成100
if (i > 200)
lutData[i] = 255; //201-255的像素灰度变成255
}
Mat lut(1, 256, CV_8UC1, lutData);
Mat a = imread("../data/test2.jpg", IMREAD_GRAYSCALE);
Mat b;
namedWindow("anjis", WINDOW_AUTOSIZE);
namedWindow("anjis1", WINDOW_AUTOSIZE);
imshow("anjis", a);
LUT(a, lut, b);
imshow("anjis1", b);
waitKey();
}
#include
using namespace cv;
int main()
{
uchar lutData[256 * 3];
for (int i = 0; i < 256; i++)
{
if (i <= 100)
{
lutData[i * 3] = 0; //R通道的0-100灰度的像素灰度变成0
lutData[i * 3 + 1] = 50;//G通道的0-100灰度的像素灰度就变成50
lutData[i * 3 + 2] = 50;//B通道的0-100灰度的像素灰度就变成50
}
if (i > 100 && i <= 200)
{
lutData[i * 3] = 100; //R通道的101-200灰度的像素灰度变成100
lutData[i * 3 + 1] = 10;//G通道的101-200灰度的像素灰度就变成10
lutData[i * 3 + 2] = 200;//B通道的101-200灰度的像素灰度就变成200
}
if (i > 200)
{
lutData[i * 3] = 255; //R通道的201-255灰度的像素灰度变成255
lutData[i * 3 + 1] = 200;//G通道的201-255灰度的像素灰度就变成200
lutData[i * 3 + 2] = 100;//B通道的201-255灰度的像素灰度就变成100
}
}
Mat lut(1, 256, CV_8UC3, lutData);
Mat a = imread("../data/test2.jpg", IMREAD_COLOR);
Mat b;
namedWindow("anjis", WINDOW_AUTOSIZE);
namedWindow("anjis1", WINDOW_AUTOSIZE);
imshow("anjis", a);
LUT(a, lut, b);
imshow("anjis1", b);
waitKey();
}
double invert(InputArray src, OutputArraydst, int flags=DECOMP_LU);
图像取反:反转图像的像素强度,使图像中的前景变为背景,背景变为前景。
显然这是一个一对一的映射,即像素值0变为255,1变为254…254变为1,255变为0。对应的查找表为lookup[256]={255,254,…,1,0}。
#include
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace std;
using namespace cv;
void Invert(Mat& img, const uchar* const lookup)
{
int rows = img.rows;
int cols = img.cols * img.channels();
for (int i = 0; i < rows; i++)
{
uchar* p = img.ptr<uchar>(i);
for (int j = 0; j < cols; j++)
p[j] = lookup[p[j]];
}
}
int main()
{
Mat src = imread("../data/test2.jpg"); //将任意一张名为test.jpg的图片放置于工程文件夹test中
if (!src.data)
{
cout << "error! The image is not built!" << endl;
return -1;
}
// 为了演示效果,将图片转换成灰度图片
Mat img1 = src;
//cvtColor( src, img1, CV_RGB2GRAY );
imshow("First", img1);
//建立查找表
uchar lookup[256];
for (int i = 0; i < 256; i++)
lookup[i] = 255 - i;
//调用自定义图像取反函数
Invert(img1, lookup);
imshow("Second", img1);
waitKey();
return 0;
}
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src = imread("../data/test2.jpg"); //将任意一张名为test.jpg的图片放置于工程文件夹test中
if (!src.data)
{
cout << "error! The image is not built!" << endl;
return -1;
}
// 为了演示效果,将图片转换成灰度图片
Mat img1 = src;
//cvtColor( src, img1, CV_RGB2GRAY );
imshow("First", img1);
//建立查找表
Mat lookUpTable(1, 256, CV_8U);
uchar* p = lookUpTable.data;
for (int i = 0; i < 256; i++)
p[i] = 255 - i;
//通过LUT函数实现图像取反
LUT(img1, lookUpTable, img1);
imshow("Second", img1);
waitKey();
return 0;
}
本次对像素的操作一共使用了6种方法,并进行计时对比,最终Opencv中的Copy方式速度是最快的,次之是指针遍历方式。
有一点就是为什么迭代的方式会比数组遍历的方式还要慢那么多,正常应该是比数组快一些才是正确的。
数组遍历方式耗时: 0.3496毫秒
行指针遍历方式耗时: 0.2317毫秒
指针遍历方式耗时: 0.3716毫秒
迭代方式耗时: 0.5014毫秒
Opencv copy方式耗时: 0.1565毫秒
LUT方式耗时: 0.4273毫秒
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
bool copyByArrayWay(Mat srcImg, Mat& resultImg);//数组at遍历方式
bool copyByRowPtrWay(Mat srcImg, Mat& resultImg);//行指针遍历方式
bool copyByPtrWay(Mat srcImg, Mat& resultImg);//指针遍历方式
bool copyByIteratorWay(Mat srcImg, Mat& resultImg);//迭代方式
bool copyByOpenCv(Mat srcImg, Mat& resultImg);//OpenCv copy方式
int main(int argv, char** argc)
{
Mat src = imread("../data/test2.jpg");
if (src.empty())
{
printf("Could not load image...\n");
return -1;
}
int64 startTime, endTime;
double usedTime;
数组遍历方式
Mat arrayWayResult = Mat::zeros(src.size(), src.type());
startTime = getTickCount(); //计时开始
copyByArrayWay(src, arrayWayResult);//数组遍历方式
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "数组遍历方式耗时:" << usedTime << "毫秒" << endl;//时间输出
imshow("arrayWay", arrayWayResult);//在OpenCV窗口中显示图像
行指针遍历方式
Mat rowPtrWayResult = Mat::zeros(src.size(), src.type());
startTime = getTickCount(); //计时开始
copyByRowPtrWay(src, rowPtrWayResult);//行指针遍历方式
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "行指针遍历方式耗时:" << usedTime << "毫秒" << endl;//时间输出
imshow("rowPtrWay", rowPtrWayResult);//在OpenCV窗口中显示图像
指针方式遍历
Mat ptrWayResult = Mat::zeros(src.size(), src.type());
startTime = getTickCount(); //计时开始
copyByPtrWay(src, ptrWayResult); //指针方式遍历
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "指针遍历方式耗时:" << usedTime << "毫秒" << endl;//时间输出
imshow("ptrWay", ptrWayResult); //在OpenCV窗口中显示图像
迭代方式遍历
Mat iterWayResult = Mat::zeros(src.size(), src.type());
startTime = getTickCount(); //计时开始
copyByIteratorWay(src, iterWayResult);//迭代方式遍历
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "迭代方式耗时:" << usedTime << "毫秒" << endl;//时间输出
imshow("iterWay", iterWayResult);//在OpenCV窗口中显示图像
OpenCv copy方式
Mat copyWayResult = Mat::zeros(src.size(), src.type());
startTime = getTickCount(); //计时开始
copyByOpenCv(src, copyWayResult);//OpenCv copy方式
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "Opencv copy方式耗时:" << usedTime << "毫秒" << endl;//时间输出
imshow("OpencvCopyWay", copyWayResult);//在OpenCV窗口中显示图像
LUT方式
Mat lookUpTable(1, 256, CV_8U);
startTime = getTickCount(); //计时开始
uchar* p = lookUpTable.data;
for (int i = 0; i < 256; ++i)
p[i] = i;
LUT(src, lookUpTable, src); //LUT
endTime = getTickCount(); //计时结束
usedTime = (endTime - startTime) / getTickFrequency() * 1000;//计算时间
cout << "LUT方式耗时: " << usedTime << "毫秒" << endl;//时间输出
imshow("LUT Way", src);//在OpenCV窗口中显示图像
waitKey(0);
return 0;
}
//数组遍历方式 at
bool copyByArrayWay(Mat srcImg, Mat& resultImg)
{
if (srcImg.empty())
{
printf("Could not load image...\n");
return false;
}
int rows = srcImg.rows;
int cols = srcImg.cols;
int ch = srcImg.channels();
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
if (ch == 3) {
resultImg.at<Vec3b>(row, col) = srcImg.at<Vec3b>(row, col);
}
else if (ch == 1) {
resultImg.at<uchar>(row, col) = srcImg.at<uchar>(row, col);
}
}
}
return true;
}
//行指针遍历方式
bool copyByRowPtrWay(Mat srcImg, Mat& resultImg)
{
if (srcImg.empty())
{
printf("Could not load image...\n");
return false;
}
int rows = srcImg.rows;
int rowPixelNums = (srcImg.cols) * (srcImg.channels());
for (int row = 0; row < rows; row++) {
uchar* srcRowPtr = srcImg.ptr<uchar>(row);
uchar* resultRowPtr = resultImg.ptr<uchar>(row);
for (int pixelNum = 0; pixelNum < rowPixelNums; pixelNum++) {
resultRowPtr[pixelNum] = srcRowPtr[pixelNum];
}
}
return true;
}
//指针遍历方式
bool copyByPtrWay(Mat srcImg, Mat& resultImg)
{
if (srcImg.empty()) {
printf("Could not load image...\n");
return false;
}
int ch = srcImg.channels();
int totalPixelNums = (srcImg.rows) * (srcImg.cols) * ch;
uchar* srcRowPtr = srcImg.ptr<uchar>(0);
uchar* resultRowPtr = resultImg.ptr<uchar>(0);
for (int pixel = 0; pixel < totalPixelNums; pixel++) {
resultRowPtr[pixel] = srcRowPtr[pixel];
}
return true;
}
//迭代方式
bool copyByIteratorWay(Mat srcImg, Mat& resultImg)
{
if (srcImg.empty()) {
printf("Could not load image...\n");
return false;
}
int ch = srcImg.channels();
if (ch == 3) {
Mat_<Vec3b>::iterator srcPtrBegin = srcImg.begin<Vec3b>();
Mat_<Vec3b>::iterator outPtrBegin = resultImg.begin<Vec3b>();
Mat_<Vec3b>::iterator srcPtrEnd = srcImg.end<Vec3b>();
while (srcPtrBegin != srcPtrEnd) {
*outPtrBegin = *srcPtrBegin;
srcPtrBegin++;
outPtrBegin++;
}
return true;
}
else if (ch == 1) {
Mat_<uchar>::iterator srcPtrBegin = srcImg.begin<uchar>();
Mat_<uchar>::iterator outPtrBegin = resultImg.begin<uchar>();
Mat_<uchar>::iterator srcPtrEnd = srcImg.end<uchar>();
while (srcPtrBegin != srcPtrEnd) {
*outPtrBegin = *srcPtrBegin;
srcPtrBegin++;
outPtrBegin++;
}
return true;
}
else
return false;
}
//OpenCv copy方式
bool copyByOpenCv(Mat srcImg, Mat& resultImg)
{
if (srcImg.empty()) {
printf("Could not load image...\n");
return false;
}
srcImg.copyTo(resultImg);
return true;
}
Mat im_gray = imread("pluto.jpg", IMREAD_GRAYSCALE);
Mat im_color;
applyColorMap(im_gray, im_color, COLORMAP_JET);
这种方式将一个灰度数据安装一定得映射方式对应上一个颜色值,灰度图里存储你的温度数据,高度数据什么的都可以
OpenCV applyColorMap默认的映射方式如下:
#include "opencv2\opencv.hpp"
#include
using namespace std;
using namespace cv;
void myColorMap(Mat& grayImg);
int main(int argc, char** argv)
{
Mat src = imread("../data/test2.jpg");
if (src.empty())
{
printf("Could not load image...\n");
return -1;
}
imshow("sourceImg", src);//显示结果
Mat grayLutDemo, dst;
//使用LUT
applyColorMap(src, dst, COLORMAP_HSV);
imshow("ColorMap", dst);//显示结果
//自定义颜色映射
cvtColor(src, grayLutDemo, COLOR_BGR2GRAY);
myColorMap(grayLutDemo);
imshow("GrayLutDemo", grayLutDemo);//显示结果
waitKey(0);
return 0;
}
void myColorMap(Mat& grayImg)
{
int lut[256];
//这个for循环中可以进行其他的操作 使相应的像素值 改变为 指定的像素值
//这里相当于对单通道图像的像素进行二值化处理
for (int i = 0; i < 256; i++)
{
if (i < 127)
{
lut[i] = 0;
}
else
lut[i] = 255;
}
int hight = grayImg.rows;
int width = grayImg.cols;
for (int row = 0; row < hight; row++)
{
for (int col = 0; col < width; col++)
{
uchar pv = grayImg.at<uchar>(row, col);
grayImg.at<uchar>(row, col) = lut[pv];
}
}
}