图像处理-Opencv入门(2)-访问图像中的像素

本文介绍了使用Opencv进行图像处理时的四种不同像素访问方法,包括指针访问、迭代器访问、动态地址访问等,并对比了它们的运行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、访问图像中像素的方法

解析:任何图像处理算法,都是从对每个像素的操作开始的,这是对图像处理算法的基本原理的理解和运用的基础,对Opencv中的函数理解和能够写出其相应功能的函数打下基础。

1.1 操作使用的主程序

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

// 函数声明
void ImgColorReduce(Mat& inputImage, Mat& outputImage, int div);

int main()
{
    // 载入图像并显示
    Mat originImage = imread("lena.png", 1);
    imshow("original", originImage);

    // 创建效果图
    Mat resultImage;
    resultImage.create(originImage.rows, originImage.cols, originImage.type());

    // 记录时间
    double timeClock = static_cast<double>(getTickCount());

    // 调用颜色空间缩减函数
    ImgColorReduce(originImage, resultImage, 32);

    // 输出时间
    timeClock = ((double)getTickCount() - timeClock) / getTickCount();
    cout << "run time:" << timeClock << "seconds" << endl;
    
    // 显示结果图
    imshow("result_colorReduce",resultImage);
    waitKey(0);
    return 0;
}

1.2 用指针访问图像元素(run time:3.37536e-08seconds)

利用C语言中的操作符[],速度快,但是相对理解抽象。

// 用指针访问像素
void ImgColorReduce(Mat& inputImage, Mat& outputImage, int div)
{
    outputImage = inputImage.clone();  // 参数克隆
    int rowNum = outputImage.rows;      // 行

    //列(每一行元素的个数=列x通道数)
    int colNUm = outputImage.cols*outputImage.channels(); 
    for (int i = 0; i < rowNum; i++)  // 遍历行
    {
        uchar* data = outputImage.ptr<uchar> (i); // 获得行的首地址
        for(int j = 0; j < colNUm; j++) // 遍历列
        {
            data[j] = data[j] / div*div + div/2;
        }

    }

}

1.3 迭代器访问图像像素(run time:5.51654e-08seconds)

需要获取图像矩阵的开始和结尾,遍历开始和结尾,通过*操作符访问相关内容,相对于指针比较安全。

// 用迭代器访问像素
void ImgColorReduce(Mat& inputImage, Mat& outputImage, int div)
{
    outputImage = inputImage.clone(); //  克隆参数
    // 获取初始和结尾迭代器
    Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();
    Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();

    // 通道颜色处理
    for(; it != itend; ++it)
    {
        (*it)[0] = (*it)[0]/div*div + div/2;
        (*it)[1] = (*it)[1]/div*div + div/2;
        (*it)[2] = (*it)[2]/div*div + div/2;
    }

}

1.4 动态地址访问图像像素(run time:3.32831e-08seconds)

相对于比较好理解,方法直观。其中cols 和rows 对应图像的宽和高。成员函数at(int y, int x)用来存取图像元素。

对于一个包含彩色图像的Mat ,会返回一个由三个8位数组组成的向量。OpenCV将此类型的向量定义为Vec3b,即由三个unsigned char  组成的向量。OpenCV中的颜色分量是BGR。

// 动态地址访问图像像素
void ImgColorReduce(Mat& inputImage, Mat& outputImage, int div)
{
    outputImage = inputImage.clone(); //  克隆参数
    // 获取图像的行列
    int rowNum = outputImage.rows;
    int colNum = outputImage.cols;

    // 处理图像像素值
    for(int i = 0; i < rowNum; i++)
    {
        for (int j = 0; j < colNum; j++)
        {
            //分别处理蓝、绿、红通道
            outputImage.at<Vec3b>(i,j)[0] = outputImage.at<Vec3b>(i,j)[0]/div*div + div/2;
            outputImage.at<Vec3b>(i,j)[1] = outputImage.at<Vec3b>(i,j)[1]/div*div + div/2;
            outputImage.at<Vec3b>(i,j)[2] = outputImage.at<Vec3b>(i,j)[2]/div*div + div/2;
        }
    }

}

1.5 编译和运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值