jashliao 用 VC++ 實現 fanfuhan OpenCV 教學004 ~ opencv-004-圖像像素讀寫操作 [一般像素存取操作(Vec3b)/指標像素存取操作(uchar *)、手工RGB顏色分離、圖片顏色反轉]
jashliao 用 VC++ 實現 fanfuhan OpenCV 教學004 ~ opencv-004-圖像像素讀寫操作 [一般像素存取操作(Vec3b)/指標像素存取操作(uchar *)、手工RGB顏色分離、圖片顏色反轉]
資料來源: https://fanfuhan.github.io/
https://fanfuhan.github.io/2019/03/21/opencv-004/
GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV
https://github.com/jash-git/jashliao-implements-FANFUHAN-OPENCV-with-VC
★前言:
★主題:
OPENCV支援直接存取圖像中各像素點的讀取與設定,方便使用者可以不透過內建函數功能自由實作自己的演算法。
★C++
// VC_FANFUHAN_OPENCV004.cpp : 定義主控台應用程式的進入點。 // #include "stdafx.h" /* // Debug | x32 通用屬性 | C/C++ | | 一般 | | 其他 Include 目錄 -> C:\opencv\build\include | | 連結器 | |一一般 | | 其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib | | |一輸入 | | 其他相依性 -> opencv_world411d.lib;%(AdditionalDependencies) // Releas | x64 組態屬性 | C/C++ | | 一般 | | 其他 Include 目錄 -> C:\opencv\build\include | | 連結器 | |一般 | | 其他程式庫目錄 -> C:\opencv\build\x64\vc15\lib | | |一輸入 | | 其他相依性 -> opencv_world411.lib;%(AdditionalDependencies) */ #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; void pause() { printf("Press Enter key to continue..."); fgetc(stdin); } int main() { Mat src = imread("../../images/l_hires.jpg");//IDE 測試路徑 , IMREAD_GRAYSCALE //Mat src = imread("../../../images/l_hires.jpg");//執行檔 測試路徑 if (src.empty()) { cout << "could not load image..." << endl; pause(); return -1; } else { namedWindow("input"); imshow("input", src); int height = src.rows; int width = src.cols; int ch = src.channels(); /* Mat color_reverse = Mat::zeros(src.size(), src.type()); Mat OnlyRed = Mat::zeros(src.size(), src.type()); Mat OnlyGreen = Mat::zeros(src.size(), src.type()); Mat OnlyBlue = Mat::zeros(src.size(), src.type()); // 直接读取图像像素,將圖片顏色反轉 for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { if (ch == 3) { Vec3b bgr = src.at<Vec3b>(row, col); Vec3b bgrreverse; Vec3b bgrRed; Vec3b bgrGreen; Vec3b bgrBlue; bgrreverse[0] = 255 - bgr[0];//依序取出藍色,並反轉 bgrreverse[1] = 255 - bgr[1];//依序取出綠色,並反轉 bgrreverse[2] = 255 - bgr[2];//依序取出紅色,並反轉 bgrRed[0] = 0; bgrRed[1] = 0; bgrRed[2] = bgr[2];; bgrGreen[0] = 0; bgrGreen[1] = bgr[1];; bgrGreen[2] = 0; bgrBlue[0] = bgr[0];; bgrBlue[1] = 0; bgrBlue[2] = 0; color_reverse.at<Vec3b>(row, col) = bgrreverse; OnlyRed.at<Vec3b>(row, col) = bgrRed; OnlyGreen.at<Vec3b>(row, col) = bgrGreen; OnlyBlue.at<Vec3b>(row, col) = bgrBlue; } else if (ch == 1) { int gray = src.at<uchar>(row, col); color_reverse.at<uchar>(row, col) = 255 - gray; } } } if (ch != 1) { namedWindow("OnlyRed"); imshow("OnlyRed", OnlyRed); namedWindow("OnlyGreen"); imshow("OnlyGreen", OnlyGreen); namedWindow("OnlyBlue"); imshow("OnlyBlue", OnlyBlue); } namedWindow("color_reverse"); imshow("color_reverse", color_reverse); //*/ //* // 指针读取 Mat result = Mat::zeros(src.size(), src.type()); Mat OnlyRed = Mat::zeros(src.size(), src.type()); Mat OnlyGreen = Mat::zeros(src.size(), src.type()); Mat OnlyBlue = Mat::zeros(src.size(), src.type()); int blue = 0, green = 0, red = 0; int gray; for (int row = 0; row < height; ++row) { // curr_row为第row行的首地址,遍历时,前三个字节表示的是第一个像素的BGR值, // 注意BGR值顺序,接下来三个字节是第二个像素的值。 uchar *curr_row = src.ptr<uchar>(row); uchar *result_row = result.ptr<uchar>(row); uchar *OnlyRed_row = OnlyRed.ptr<uchar>(row); uchar *OnlyGreen_row = OnlyGreen.ptr<uchar>(row); uchar *OnlyBlue_row = OnlyBlue.ptr<uchar>(row); for (int col = 0; col < width; ++col) { if (ch == 3) { blue = *curr_row++; green = *curr_row++; red = *curr_row++; *result_row++ = 255 - blue; *result_row++ = 255 - green; *result_row++ = 255 - red; *OnlyRed_row++ = 0; *OnlyRed_row++ = 0; *OnlyRed_row++ = red; *OnlyGreen_row++ = 0; *OnlyGreen_row++ = green; *OnlyGreen_row++ = 0; *OnlyBlue_row++ = blue; *OnlyBlue_row++ = 0; *OnlyBlue_row++ = 0; } else if (ch == 1) { gray = *curr_row++; *result_row++ = gray; } } } if (ch != 1) { namedWindow("OnlyRed"); imshow("OnlyRed", OnlyRed); namedWindow("OnlyGreen"); imshow("OnlyGreen", OnlyGreen); namedWindow("OnlyBlue"); imshow("OnlyBlue", OnlyBlue); } namedWindow("result"); imshow("result", result); //*/ waitKey(0); } return 0; }
★Python
import cv2 as cv src = cv.imread("../images/liuyifei_1.png") cv.namedWindow("input", cv.WINDOW_AUTOSIZE) cv.imshow("input", src) h, w, ch = src.shape print("h , w, ch", h, w, ch) for row in range(h): for col in range(w): b, g, r = src[row, col] b = 255 - b g = 255 - g r = 255 - r src[row, col] = [b, g, r] cv.imshow("output", src) cv.waitKey(0) cv.destroyAllWindows()
★結果圖:
★延伸說明/重點回顧:
OPENCV要知道彩色圖片與灰階圖片是透過Mat的成員函數channels()回傳值來進行判斷(分別/判別)。
OPENCV的彩色圖片RGB的存取/儲存順序為B、G、R。