1. 程式人生 > >OpenCV 分離顏色通道 影象混合 亮度對比度調整

OpenCV 分離顏色通道 影象混合 亮度對比度調整

OpenCV 分離顏色通道 影象混合 亮度對比度調整

概述

  1. 讀取兩張圖片,將一張圖片插入另一張圖片進行混合
  2. 將圖片1的顏色通道分離
  3. 分別將圖片2插入圖片1的藍色和紅色通道進行混合
  4. 合併顏色通道
  5. 調整合並後圖像的亮度和對比度
    懶,圖片素材直接取自淺墨的圖片。

程式碼段

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
/*視窗相關變數*/
#define WinName "showImage"
int lightness = 80;
int contrast = 80;
void on_trackbar(int, void*);
bool createWin();
/*通道混合相關變數*/
vector<Mat> g_MatCh;
Mat g_imageBlueCh;
Mat g_imageGreenCh;
Mat g_imageRedCh;

Mat g_srcImage, g_dstImage,g_mask;
Mat imageROI;
bool
main() { g_srcImage = imread("dota_pa.jpg"); /*第二個引數很重要 這裡將圖片以灰度圖方式傳入 這樣在後面加權平均時才不會發生記憶體溢位*/ g_mask = imread("dota_logo.jpg",0); if (!g_srcImage.data) { cout << "srcImage load failure" << endl; return false; }//判斷影象是否成功載入 if (!g_mask.data) { cout << "mask load failure"
<< endl; return false; } split(g_srcImage, g_MatCh); //分離各通道 g_imageBlueCh = g_MatCh.at(0); g_imageGreenCh = g_MatCh.at(1); g_imageRedCh = g_MatCh.at(2); createWin();//建立視窗 //回撥函式初始化 on_trackbar(lightness, 0); on_trackbar(contrast, 0); waitKey(0); } /*建立視窗和trackbar*/ bool createWin() { namedWindow(WinName); createTrackbar("lightness", WinName, &lightness, 200, on_trackbar); createTrackbar("contrast", WinName, &contrast, 300, on_trackbar); return true; } /*TrackBar 回撥函式*/ void on_trackbar(int, void*) { imageROI = g_imageBlueCh(Rect(200, 250, g_mask.cols, g_mask.rows)); //在藍色通道劃定感興趣區域 addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0, imageROI); imshow("藍色通道疊加後", g_imageBlueCh); imageROI = g_imageRedCh(Rect(200, 250, g_mask.cols, g_mask.rows)); //在紅色通道劃定感興趣區域 addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0, imageROI); imshow("紅色通道疊加後", g_imageRedCh); merge(g_MatCh, g_dstImage); //合併各通道 /*亮度對比度調整*/ for(int y=0;y<g_dstImage.rows;y++) for(int x=0;x<g_dstImage.cols;x++) for (int c = 0; c < 3; c++) { g_dstImage.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(((contrast*0.01)*g_dstImage.at<Vec3b>(y, x)[c]) + lightness); } imshow(WinName, g_dstImage); }

程式執行效果

藍色通道疊加logo後的效果
圖1 藍色通道疊加後的效果

紅色通道疊加後的效果
圖2 紅色通道疊加後的效果
最終效果
圖3 合併通道後的效果

效果分析

在一張圖中一個畫素的色彩組成可以從通道分離後看出。例如 *圖1 藍色通道* 在原圖中藍色約深的地方,在圖1 中表現的更明亮,反之,則更暗。分別將logo混合進藍色通道和紅色通道後 ,再將各通道合併,將得到紫色的logo。 在亮度和對比度調整時,要對每一個畫素的每一個通道進行調整。一般遍歷圖象是2重迴圈,這裡出現了三重迴圈,最裡面一層則是分別訪問每個畫素的B、G、R通道。 這種點操作(亮度調整和對比度調整)的理論公式為:
                               g(i,j)=a*f(i,j)+b
其中a稱為增益(gain),常用來控制對比度。b稱為偏置(bias),常用來控制亮度。f(i,j)為影象中每個畫素。g(i,j)為計算後的畫素值。

注意事項

在這個程式中容易出現的幾種問題:
  1. 單通道影象不能和多通道影象混合,否則將記憶體溢位。g_mask = imread("dota_logo.jpg",0); 第二個引數意義為將圖片以灰度圖讀入,在後面的與單通道影象混合時才不至於引發錯誤。
  2. addWeighted(imageROI, 0.5, g_mask, 0.5, 0.0,imageROI); 最後一個引數為ROI,為原影象的引用,因此將加權疊加後的影象輸出到ROI即改變了原影象對應的區域。
  3. 在調整影象時為了避免畫素值溢位需要加上saturate_cast<uchar>

心得

影象較大時,遍歷處理每一個畫素將會對程式效能造成很大影響,因此在編寫影象處理程式時還得考慮如何提高效率。加油。