OpenCV计算机视觉编程之三种图像像素的遍历方法
為了構建計算機視覺應用程序,需要學會訪問圖像內容,有時也要修改或創建圖像,如何操作圖像的像素,就需要遍歷一幅圖像并處理每一個像素。現在我們就來介紹OpenCV三種圖像像素的遍歷方法:
一、 用cv::Mat類的at方法掃描圖像
利用cv::Mat的at(int x,int y)方法可以訪問元素,其中x是行號,y是列號。在編譯時必須明確方法返回值的類型,因為cv::Mat可以接受任何類型的元素,所以程序員需要指定返回值的預期類型。正因為如此,at方法被實現成一個模板方法。在調用at方法時,你必須指定圖像元素的類型,例如:
| 001 002 003 004 | // 單通道圖像 image.at<uchar>(i,j)= 255; // 三通道圖像 image.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255); |
用cv::Mat類的at方法掃描圖像代碼如下:
| 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 | void visit_mat_by_at(cv::Mat &img) { ????for (int i = 0; i < img.rows; i++) ????{ ????????for (int j = 0; j < img.cols; j++) ????????{ ????????????// 單通道圖像 ????????????if (img.channels() == 1) ????????????{ ????????????????img.at<uchar>(i, j) += 50; ????????????} ????????????// 三通道圖像 ????????????else ????????????{ ????????????????img.at<cv::Vec3b>(i, j)[0] += 50; ????????????????img.at<cv::Vec3b>(i, j)[1] += 50; ????????????????img.at<cv::Vec3b>(i, j)[2] += 50; ????????????} ????????} ????} } |
二、 用指針掃描圖像
一般來說,用指針掃描圖像比較高效。在大多數圖像處理任務中,執行計算時你都需要對圖像的所有像素進行掃描。需要訪問的像素數量非常龐大,因此你必須采用高效的方式來執行這個任務。
用指針掃描圖像代碼如下:
| 001 002 003 004 005 006 007 008 009 010 011 | void visit_mat_by_pointer(cv::Mat &img) { ????for (int i = 0; i < img.rows; i++) ????{ ????????uchar *data = img.ptr<uchar>(i); ????????for (int j = 0; j < img.cols * img.channels(); j++) ????????{ ????????????data[j] += 50; ????????} ????} } |
三、 用迭代器掃描圖像
在面向對象編程時,我們通常用迭代器對數據集合進行循環遍歷。迭代器是一種類,專門用于遍歷集合的每個元素,并能隱藏遍歷過程的具體細節。標準模板庫(Standard Template Library,STL)對每個集合類都定義了對應的迭代器類,OpenCV也提供了cv::Mat的迭代器類,并且與C++ STL中的標準迭代器兼容。
用迭代器掃描圖像代碼如下:
| 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 | void visit_mat_by_iterator(cv::Mat &img) { ????// 單通道圖像 ????if (img.channels() == 1) ????{ ????????cv::Mat_<uchar>::iterator begin = img.begin<uchar>(); ????????cv::Mat_<uchar>::iterator end = img.end<uchar>(); ? ????????for (auto it = begin; it != end; it++) ????????{ ????????????*it += 50; ????????} ????} ????// 三通道圖像 ????else ????{ ????????cv::Mat_<cv::Vec3b>::iterator begin = img.begin<cv::Vec3b>(); ????????cv::Mat_<cv::Vec3b>::iterator end = img.end<cv::Vec3b>(); ? ????????for (auto it = begin; it != end; it++) ????????{ ????????????(*it)[0] += 50; ????????????(*it)[1] += 50; ????????????(*it)[2] += 50; ????????} ????} } |
測試代碼:
| 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 | #include <iostream> #include <opencv2/opencv.hpp> ? int main() { ????// 單通道圖像 ????cv::Mat img1(3, 4, CV_8UC1, 100); ????std::cout << "單通道圖像像素修改前:" << std::endl; ????std::cout << img1 << std::endl; ? ????visit_mat_by_at(img1); ????//visit_mat_by_pointer(img1); ????//visit_mat_by_iterator(img1); ????std::cout << "單通道圖像像素修改后:" << std::endl; ????std::cout << img1 << std::endl; ? ????// 三通道圖像 ????cv::Mat img2(3, 4, CV_8UC3, cv::Scalar(100, 150, 200)); ????std::cout << "三通道圖像像素修改前:" << std::endl; ????std::cout << img2 << std::endl; ? ????visit_mat_by_at(img2); ????//visit_mat_by_pointer(img2); ????//visit_mat_by_iterator(img2); ????std::cout << "三通道圖像像素修改后:" << std::endl; ????std::cout << img2 << std::endl; ? ????cv::waitKey(); ? ????return 0; } |
運行結果:
| 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 | 單通道圖像像素修改前: [100, 100, 100, 100; ?100, 100, 100, 100; ?100, 100, 100, 100] 單通道圖像像素修改后: [150, 150, 150, 150; ?150, 150, 150, 150; ?150, 150, 150, 150] 三通道圖像像素修改前: [100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200; ?100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200; ?100, 150, 200, 100, 150, 200, 100, 150, 200, 100, 150, 200] 三通道圖像像素修改后: [150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250; ?150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250; ?150, 200, 250, 150, 200, 250, 150, 200, 250, 150, 200, 250] |
說明我們完成遍歷圖像,并成功修改圖像像素,至此大功告成~
總結
以上是生活随笔為你收集整理的OpenCV计算机视觉编程之三种图像像素的遍历方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python语言编程之批量文件重命名
- 下一篇: PyCharm常用快捷键大全