jashliao 用 VC++ 實現 fanfuhan OpenCV 教學005 ~ opencv-005-像素(pixel)計算操作 [圖片合成(加/減/乘/除)]

jashliao 用 VC++ 實現 fanfuhan OpenCV 教學005 ~ opencv-005-像素(pixel)計算操作 [圖片合成(加/減/乘/除)]

jashliao 用 VC++ 實現 fanfuhan OpenCV 教學005 ~ opencv-005-像素(pixel)計算操作 [圖片合成(加/減/乘/除)]


資料來源: https://fanfuhan.github.io/

https://fanfuhan.github.io/2019/03/23/opencv-005/


GITHUB:https://github.com/jash-git/fanfuhan_ML_OpenCV

https://github.com/jash-git/jashliao-implements-FANFUHAN-OPENCV-with-VC


★前言:

★主題:
    OPENCV提供等大且格式相同的兩張圖片進行四則運算的對應函數。


    四則運算相關函數如下所列:

        圖像相加: add(src1, src2, add_result);
        圖像戴權種值相加(透明效果):addWeighted(src1, 0.5, src2, (1.0 – 0.5), 0.0, add_weight_result);
        圖像相減: subtract(src1, src2, sub_result);
        圖像相乘: multiply(src1, src2, mul_result);
        圖像相除: divide(src1, src2, div_result);

C++

// VC_FANFUHAN_OPENCV005.cpp : 定義主控台應用程式的進入點。
//
/*
// 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 "stdafx.h"
#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 src1 = imread("../../images/LinuxLogo.jpg");
	Mat src2 = imread("../../images/WindowsLogo.jpg");
	//Mat image = imread("../../../images/l_hires.jpg", IMREAD_GRAYSCALE);//執行檔 測試路徑

	if (src1.empty() || src2.empty()) {
		cout << "could not load image..." << endl;
		pause();
		return -1;
	}
	else
	{
		imshow("input1", src1);
		imshow("input2", src2);

		// 加法
		Mat add_result = Mat::zeros(src1.size(), src1.type());
		add(src1, src2, add_result);
		imshow("add_result", add_result);

		// 带权重的加法,一般推荐使用这个 浮水印 透明感
		Mat add_weight_result = Mat::zeros(src1.size(), src1.type());
		addWeighted(src1, 0.5, src2, (1.0 - 0.5), 0.0, add_weight_result);
		imshow("add_weight_result", add_weight_result);

		// 减法
		Mat sub_result = Mat::zeros(src1.size(), src1.type());
		subtract(src1, src2, sub_result);
		imshow("sub_result", sub_result);

		// 乘法
		Mat mul_result = Mat::zeros(src1.size(), src1.type());
		multiply(src1, src2, mul_result);
		imshow("mul_result", mul_result);

		// 除法
		Mat div_result = Mat::zeros(src1.size(), src1.type());
		divide(src1, src2, div_result);
		imshow("div_result", div_result);

		// 自己实现加法操作
		int b1 = 0, g1 = 0, r1 = 0;
		int b2 = 0, g2 = 0, r2 = 0;

		Mat my_add_result = Mat::zeros(src1.size(), src1.type());
		for (int row = 0; row < src1.rows; ++row) {
			for (int col = 0; col < src1.cols; ++col) {
				b1 = src1.at<Vec3b>(row, col)[0];
				g1 = src1.at<Vec3b>(row, col)[1];
				r1 = src1.at<Vec3b>(row, col)[2];

				b2 = src2.at<Vec3b>(row, col)[0];
				g2 = src2.at<Vec3b>(row, col)[1];
				r2 = src2.at<Vec3b>(row, col)[2];

				// b1:0~255,b2:0~255, b1+b2可能大于255,所以需要转换,通过saturate_cast<uchar>()
				my_add_result.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b1 + b2);
				my_add_result.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g1 + g2);
				my_add_result.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r1 + r2);
			}
		}

		imshow("my_add_result", my_add_result);

		imwrite("add_result.jpg", add_result);
		imwrite("add_weight_result.jpg", add_weight_result);
		imwrite("sub_result.jpg", sub_result);
		imwrite("div_result.jpg", div_result);

		waitKey(0);
	}

	return 0;
}



Python

import cv2 as cv
import numpy as np

src1 = cv.imread("../images/opencv_images/LinuxLogo.jpg");
src2 = cv.imread("../images/opencv_images/WindowsLogo.jpg");
cv.imshow("input1", src1)
cv.imshow("input2", src2)
h, w, ch = src1.shape
print("h , w, ch", h, w, ch)

add_result = np.zeros(src1.shape, src1.dtype);
cv.add(src1, src2, add_result);
cv.imshow("add_result", add_result);

sub_result = np.zeros(src1.shape, src1.dtype);
cv.subtract(src1, src2, sub_result);
cv.imshow("sub_result", sub_result);

mul_result = np.zeros(src1.shape, src1.dtype);
cv.multiply(src1, src2, mul_result);
cv.imshow("mul_result", mul_result);

div_result = np.zeros(src1.shape, src1.dtype);
cv.divide(src1, src2, div_result);
cv.imshow("div_result", div_result);

cv.waitKey(0)
cv.destroyAllWindows()


★結果圖:



★延伸說明/重點回顧:

    想要使用OPENCV提供的四則運算函數前提條件必須是在兩張被運算圖像的類型類型、通道數據、大小都必須相同情況下


    由於上述的使用條件,當我們要自己撰寫類似功能時,記得使用saturate_cast <T> (value) 進行類型轉換,確保運算結果介於0~255,藉此預防運算錯誤。


    PS.影像(圖像)處理中: 黑色(0,0,0) 白色(255,255,255)


發表迴響

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