Opencv学习笔记(二)访问像素的三种方法

一、使用动态地址访问

下面的代码把红色通道值大于128的颜色的置为白色

#include<iostream>    
#include<opencv2/opencv.hpp>    


using namespace cv;
using namespace std;


void GetImg()
{
    double start = static_cast<double>(getTickCount());
    Mat srcImg, dstImg;
    srcImg = imread("D:\\1.png", 1);
    dstImg = srcImg.clone();
    for (int i = 0; i < dstImg.rows; i++)
    {
        for (int j= 0; j < dstImg.cols; j++)
        {
            if (dstImg.at<Vec3b>(i, j)[2] >190)
            {
                dstImg.at<Vec3b>(i, j)[0] = 0;
                dstImg.at<Vec3b>(i, j)[1] = 0;
                dstImg.at<Vec3b>(i, j)[2] = 255;
            }
            else
            {
                dstImg.at<Vec3b>(i, j)[0] = 0;
                dstImg.at<Vec3b>(i, j)[1] = 0;
                dstImg.at<Vec3b>(i, j)[2] = 0;
            }
        }
    }
    double end = static_cast<double>(getTickCount());
    double time = (end - start) / getTickFrequency();
    cout << "运行时间为:" << time << "秒" << endl;
    imshow("原图像", srcImg);
    imshow("阈值处理后图像", dstImg);
    waitKey(0);

}


二、使用指针地址访问

  我们的算法在遍历图像的全部像素时,利用上述.at方法会很慢,利用指针会更高效。

  基本方法是获取一行像素的头指针。对于灰度图像有:

uchar* data = image.ptr<uchar>(i);

 如果图像是24位彩色,则有:

cv::Vec3b * data = image.ptr<cv::Vec3b>(i);
void GetGreyImgByPointer()
{
    double start = static_cast<double>(getTickCount());
    Mat srcImg, dstImg;
    srcImg = imread("D:\\1.png", 0);
    dstImg = srcImg.clone();    // 不建议使用原图,深复制
    int row = dstImg.rows;
    int col = dstImg.cols * dstImg.channels();  //将三通道转化为一通道
    for (int i = 0; i < row; i++)
    {
        uchar * data = dstImg.ptr<uchar>(i);    //    获取每行首地址
        for (int j = 0; j < col; j++)
        {
            if (data[j] > 90)
            {
                data[j] = 255;
            }
            else
            {
                data[j] = 0;
            }
        }
    }
    double end = static_cast<double>(getTickCount());
    double time = (end - start) / getTickFrequency();
    cout << "运行时间为:" << time << "秒" << endl;
    imshow("原图像", srcImg);
    imshow("阈值处理后的图像", dstImg);
    waitKey(0);
}

void GetColorImgByPointer()
{
    double start = static_cast<double>(getTickCount());
    Mat srcImg, dstImg;
    srcImg = imread("D:\\1.png",1);
    dstImg = srcImg.clone();
    int row = dstImg.rows;
    int col = dstImg.cols * dstImg.channels(); 
    for (int i = 0; i < row; i++)
    {
        Vec3b* data = dstImg.ptr<Vec3b>(i);
        for (int j = 0; j < col; j++)
        {
            if (data[j][2] > 190)
            {
                data[j][0] = 0;
                data[j][1] = 0;
                data[j][2] = 255;
            }
            else
            {
                data[j][0] = 0;
                data[j][1] = 0;
                data[j][2] = 0;

            }
        }
    }
    double end = static_cast<double>(getTickCount());
    double time = (end - start) / getTickFrequency();
    cout << "运行时间为:" << time << "秒" << endl;
    imshow("原图像:", srcImg);
    imshow("阈值处理后的图像", dstImg);
    waitKey(0);
}



三、使用迭代器访问

对于一个Mat,创建一个Mat::Iterator对象it和itend,通过it = Mat::begin()来得到迭代首地址,itend=Mat::end()来得到尾地址,it!=itend来判断是否到尾,it++得到下一个像素指向,(*it)来得到实际像素。

void GetGrayImgByInterator()
{
	double start = static_cast<double>(getTickCount());
	Mat srcImg, dstImg;
	srcImg = imread("D:\\1.png", 0);
	dstImg = srcImg.clone();

	Mat_<uchar>::iterator it = dstImg.begin<uchar>();
	Mat_<uchar>::iterator itend = dstImg.end<uchar>();
	for ( ; it != itend; it++)
	{
		if (*it > 90)
		{
			*it = 255;
		}
		else
		{
			*it = 0;
		}
	}
	double end = static_cast<double>(getTickCount());
	double time = (end - start) / getTickFrequency();
	cout << "运行时间为:" << time << "秒" << endl;
	imshow("原图像:", srcImg);
	imshow("阈值处理后的图像", dstImg);
	waitKey(0);
}

void GetColorImgByInterator()
{
	double start = static_cast<double>(getTickCount());
	Mat srcImg, dstImg;
	srcImg = imread("D:\\1.png", 1);
	dstImg = srcImg.clone();
	Mat_<Vec3b>::iterator it = dstImg.begin<Vec3b>();
	Mat_<Vec3b>::iterator itend = dstImg.end<Vec3b>();
	for ( ; it != itend; it++)
	{
		if ((*it)[2] > 190)
		{
			(*it)[0] = 0;
			(*it)[1] = 0;
			(*it)[2] = 255;

		}
		else
		{
			(*it)[0] = 0;
			(*it)[1] = 0;
			(*it)[2] = 0;
		}
	}
	double end = static_cast<double>(getTickCount());
	double time = (end - start) / getTickFrequency();
	cout << "时间:" << time << "秒" << endl;
	imshow("原图像", srcImg);
	imshow("阈值处理后的图像", dstImg);
	waitKey(0);

}


猜你喜欢

转载自blog.csdn.net/xyu66/article/details/79929871