OpenCV入门系列 —— cv::Mat图像数据遍历、读取像素

OpenCV入门系列 —— cv::Mat图像数据遍历、读取像素


前言

随着工业自动化、智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别、定位、抓取、测量,缺陷检测等),而针对不同作业场景进行解决方案设计时,通常会借助PCL、OpenCV、Eigen等简单方便的开源算法库进行方案的快速验证和迭代以满足作业场景下的目标需求。

为了让对工业机器视觉方向感兴趣的同学能够少走一些弯路,故推出了此一系列简易入门教程示例,让初次使用者能够最简单直观地感受到当前所用算法模块的执行效果。

后续会逐步扩增与工业机器视觉相关的一些其它内容,如:

项目案例剖析场景数据分析基础算法模块相机评测 等;

如有兴趣可加入群聊(若入群二维码被屏蔽,则可以通过Q群(1032861997)或评论、私信博主“群聊”,邀请入群),与同道同学及圈内同行一起交流讨论。

在这里插入图片描述


程序说明

对cv::Mat图像数据两种像素遍历方式的时耗对比;

输出结果

在这里插入图片描述

element type: 16
width: 600 height:450 total: 270000
traversal_1 time cost: 0.253593 ms
traversal_2 time cost: 0.102666 ms

代码示例

/*
 * @File: read_pixel.cpp
 * @Brief: opencv course
 * @Description: 对cv::Mat图像数据两种像素遍历方式的时耗对比
 * @Version: 0.0.1
 * @Author: MuYv
 */
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>


void traversal_1(const cv::Mat& img_src, cv::Mat& img_processed);
void traversal_2(const cv::Mat& img_src, cv::Mat& img_processed);


int main(int argc, char** argv){
    
    
    if(argc != 2){
    
    
        std::cout<<"Usage: exec img_file_path"<<std::endl;
        return -1;
    }
    const std::string kImgFilePath = argv[1];   // "../imgs/fruit.png"

    // cv::Mat img_src = cv::imread(kImgFilePath, cv::IMREAD_UNCHANGED);
    cv::Mat img_src = cv::imread(kImgFilePath, cv::IMREAD_COLOR);
    std::cout<<"element type: "<<img_src.type()<<std::endl; 

    const int kHeight = img_src.rows;
    const int kWidth = img_src.cols;
    std::cout<<"width: "<<kWidth<<"  height:"<<kHeight<<"  total: "<<(kWidth*kHeight)<<std::endl;

    cv::Mat img_tmp;

    // 此处提供两种较为常用且易理解的方案
    traversal_1(img_src, img_tmp);
    traversal_2(img_src, img_tmp);

    cv::imshow("img_src", img_src);
    cv::imshow("img_tmp", img_tmp);

    cv::waitKey(0);

    return 0;
}
void traversal_1(const cv::Mat& img_src, cv::Mat& img_processed){
    
    
    const int kHeight = img_src.rows;
    const int kWidth = img_src.cols;
    img_processed = img_src.clone();
    double t1 = cv::getTickCount();

    for(int row=0; row<kHeight; ++row){
    
    
        for(int col=0; col<kWidth; ++col){
    
    
            auto& rgb = img_processed.at<cv::Vec3b>(row,col);
            rgb[0] = 255 - rgb[0];
            rgb[1] = 255 - rgb[1];
            rgb[2] = 255 - rgb[2];
        }
    }

    double t2 = cv::getTickCount();
    double time_cost = ((t2-t1)/cv::getTickFrequency())*1000.0;

    std::cout<<"time cost: "<<time_cost<<" ms"<<std::endl;
}
void traversal_2(const cv::Mat& img_src, cv::Mat& img_processed){
    
    
    const int kHeight = img_src.rows;
    const int kWidth = img_src.cols;
    img_processed = img_src.clone();
    double t1 = cv::getTickCount();

    for(int row=0; row<kHeight; ++row){
    
    
        auto row_data = img_processed.ptr<cv::Vec3b>(row);
        for(int col=0; col<kWidth; ++col){
    
    
            auto& rgb = row_data[col];
            rgb[0] = 255 - rgb[0];
            rgb[1] = 255 - rgb[1];
            rgb[2] = 255 - rgb[2];
        }
    }

    double t2 = cv::getTickCount();
    double time_cost = ((t2-t1)/cv::getTickFrequency())*1000.0;

    std::cout<<"time cost: "<<time_cost<<" ms"<<std::endl;
}

总结

在进行方案效果验证时,可以不过多关注整体算法的运行时耗,以方案效果可行性验证为主;
后续整体解决方案的效果满足要求时,再结合方案流程及代码工程化手段对时耗、内存等做针对性优化;


注:部分测试所用图片数据来源于网络,如有侵权,请联系博主删除,谢谢。

猜你喜欢

转载自blog.csdn.net/memorynode/article/details/124283243