jashliao 用 VC++ 實現 fanfuhan OpenCV 教學004 ~ opencv-004-圖像像素讀寫操作 [一般像素存取操作(Vec3b)/指標像素存取操作(uchar *)、手工RGB顏色分離、圖片顏色反轉]

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


發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *