通過設定Scalar算子的算術運算操作
void QuickDemo::operator_demo(Mat& img)
{
//演示畫布任意操作
Mat dst;
dst = img + Scalar(50, 50, 50);//這樣加法的操作之后會發現圖片會亮一些
/*
imshow("src", img);
imshow("dst", dst);
*/
dst = img - Scalar(50, 50, 50);//這樣減法的操作之后會發現圖片會亮一些
//dst = img / Scalar(2, 2, 2);//這樣除法操作之后會發現圖片暗一些
//dst = img * Scalar(2, 2, 2);//這樣的操作是錯誤的,會報錯,原因是不同型別的資料不能混合運算
//以下來演示乘法運算該如何操作
//1.創建和原本src相同尺寸型別的畫布
Mat drawer = Mat::zeros(img.size(), img.type());
//2.用Scalar設定畫布的初始灰度值
drawer = Scalar(2, 2, 2);
//3.用multiply()進行運算
//語法說明(要乘的影像,要乘的影像,輸出影像承載)
multiply(drawer, img, dst);
//test
imshow("src", img);
imshow("dst", dst);
}
通過這個例子我們可以知道,Scalar實際上是一種算子,可以對每一個像素點進行運算,運算值是灰度值.
運算用法撰寫的demo
void QuickDemo::operator_demo(Mat& img)
{
//演示畫布任意操作
Mat dst;
dst = img + Scalar(50, 50, 50);//這樣加法的操作之后會發現圖片會亮一些
dst = img - Scalar(50, 50, 50);//這樣減法的操作之后會發現圖片會亮一些
dst = img / Scalar(2, 2, 2);//這樣除法操作之后會發現圖片暗一些
dst = img * Scalar(2, 2, 2);//這樣的操作是錯誤的,會報錯,原因是不同型別的資料不能混合運算
//下面通過逐個像素點的相加的演算法來表現加法
//1.定義常用參量
int n = img.rows;
int m = img.cols;
int dims = img.channels();
//2.判斷并進行逐點的操作
Mat drawer = Mat::zeros(img.size(),img.type());
drawer = Scalar(50, 50, 50);
Mat dst = drawer.clone();
if (dims == 1)//單通道
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
//這一點要特別注意,相加有可能會超過255,所以這邊為了避免這種情況,要做一個防溢位
dst.at<uchar>(i, j) = saturate_cast<uchar>(drawer.at<uchar>(i,j)+img.at<uchar>(i,j));
}
}
}
if (dims == 3)//三通道
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
Vec3b p1 = img.at<Vec3b>(i, j);
Vec3b p2 = drawer.at<Vec3b>(i, j);
dst.at<Vec3b>(i, j) = saturate_cast<uchar>(p1[0] + p2[0]);
dst.at<Vec3b>(i, j) = saturate_cast<uchar>(p1[1] + p2[1]);
dst.at<Vec3b>(i, j) = saturate_cast<uchar>(p1[2] + p2[2]);
}
}
}
Mat dst;
//下面介紹api的用法
//以下來演示乘法運算該如何操作
//1.創建和原本src相同尺寸型別的畫布
Mat drawer = Mat::zeros(img.size(), img.type());
//2.用Scalar設定畫布的初始灰度值
drawer = Scalar(2, 2, 2);
//3.用multiply()進行運算
//語法說明(要乘的影像,要乘的影像,輸出影像承載)
multiply(drawer, img, dst);
cv::add(img, drawer, dst);
//add的用法是(要加的影像,要加的影像,輸出影像)
cv::subtract(img, drawer, dst);
cv::divide(img, drawer, dst);
cv::multiply(img, drawer, dst);
//test
imshow("src", img);
imshow("dst", dst);
}
滾動條演示調節亮度等引數(OpencvGUI)
demo01初體驗
Mat src, dst, m;
int lightness = 50;
static void on_track(int , void *)//void意為任意型別的函式均可
{
m = Scalar(lightness, lightness, lightness);
//再呼叫api調節亮度
cv::add(src, m, dst);
//實時顯示視窗
imshow("亮度調節", dst);
}
void QuickDemo::track_bar_demo(Mat& img)
{
//1.創建一個視窗
namedWindow("亮度調整", WINDOW_AUTOSIZE);
//2.調整上下值的限度
int maxval = 100; //分別為所調整的最大亮度和初始亮度
src = img.clone();
m = Mat::zeros(img.size(), img.type());
dst = Mat::zeros(img.size(), img.type());
//3.創建滑動條
//語法說明:("char(trackerbar的名字)","char(視窗的名稱)","(int)需要改變的value","所能達到的最大值","(function)引起改變之后所回呼的函式","(void)任意外帶引數")
createTrackbar("value_bar", "亮度調整", &lightness,maxval,on_track);
on_track(50, 0);
}
這里對回呼函式需要解釋一下,意思是當產生了一個事件之后,系統捕獲到了這個事件,就會把引數傳回到callback函式中去,
總結來說:實作這個功能,首先需要一個視窗來承載trackerbar,然后設定好畫布算子,然后撰寫回呼函式,把傳回來的引數利用起來即可,
優化版本,傳遞變數
static void on_track(int modify_value, void* userdata)//void意為任意型別的函式均可
{
Mat img = *(Mat*) userdata;//將傳建進來的img資料強轉為Mat型別
Mat m = Mat::zeros(img.size(), img.type());
Mat src = img.clone();
Mat dst;
m = Scalar(modify_value, modify_value, modify_value);
//再呼叫api調節亮度
cv::add(src , m, dst);
//實時顯示視窗
imshow("亮度調整", dst);
}
void QuickDemo::track_bar_demo(Mat& img)
{
//1.創建一個視窗
namedWindow("亮度調整", WINDOW_AUTOSIZE);
//2.調整上下值的限度
int maxval = 100; //分別為所調整的最大亮度和初始亮度
int lightness = 50;
//3.創建滑動條
//語法說明:("char(trackerbar的名字)","char(視窗的名稱)","(int)需要改變的value","所能達到的最大值","(function)引起改變之后所回呼的函式","(void)任意外帶引數")
createTrackbar("value_bar", "亮度調整", &lightness,maxval,on_track,(void*)(&img));
on_track(50, &img);
}
如果需要同時調節亮度和對比度的話,就需要同時使用兩個trackbar,同時合成兩幅影像,要用addweight這個api
static void on_light(int modify_value, void* userdata)//萬能指標 void意為任意型別的函式均可
{
Mat img = *((Mat*) userdata);//將傳建進來的img資料強轉為Mat型別
Mat m = Mat::zeros(img.size(), img.type());
Mat src = img.clone();
Mat dst= Mat::zeros(img.size(), img.type());
//再呼叫api調節亮度
//此處是一個影像融合操作 呼叫cv::addWeighted()函式介面
//dst=src1*alpha+src2*beta+gamma
addWeighted(src, 1.0, m, 0.0, modify_value, dst);
//實時顯示視窗
imshow("亮度與對比度調整", dst);
}
static void on_contract(int modify_value, void* userdata)//萬能指標 void意為任意型別的函式均可
{
Mat img = *((Mat*)userdata);//將傳建進來的img資料強轉為Mat型別
Mat m = Mat::zeros(img.size(), img.type());
Mat src = img.clone();
Mat dst= Mat::zeros(img.size(), img.type());
//此處是一個影像融合操作 呼叫cv::addWeighted()函式介面
//為了精確地使用對比度,采用以下的方法
//dst=src1*alpha+src2*beta+gamma
double contract_val = modify_value / 100.0;
addWeighted(src, contract_val, m, 0.0,0,dst);
//實時顯示視窗
imshow("亮度與對比度調整", dst);
}
void QuickDemo::track_bar_demo(Mat& img)
{
//1.創建一個視窗
namedWindow("亮度與對比度調整", WINDOW_AUTOSIZE);
//2.調整上下值的限度
int maxval_light = 100,lightness=50; //分別為所調整的最大亮度和初始亮度
int maxval_contract =200, contractness = 120;//分別為最大的對比度和初始對比度
//3.創建滑動條
//語法說明:("char(trackerbar的名字)","char(視窗的名稱)","(int)需要改變的value","所能達到的最大值","(function)引起改變之后所回呼的函式","(void)任意外帶引數")
createTrackbar("light_bar", "亮度與對比度調整", &lightness, maxval_light,on_light,(void*)(&img));//這個回呼函式用來解決亮度的問題
createTrackbar("contract_bar", "亮度與對比度調整", &contractness, maxval_contract, on_contract, (void*)(&img));//這個回呼函式用來解決對比度的問題
on_light(50, &img);
}
總結一下滾動條,其實就是為不同的滾動條的資料提供不同的方法,如果是多種引數共同調節的話就要使用addWeight來實作,
重點是要學到addWeight這個函式的用法:改變亮度,我們通過改變加的gamma來改變Mat陣列內每一個點的灰度值
改變對比度,那就是通過alpha的值來改變,改變比值,從而產生對比的這一種效果,
簡單鍵盤操作的應用
void QuickDemo::key_demo(Mat& img)
{
//本demo用于演示用鍵盤來操作影像
char c;
Mat dst = Mat::zeros(img.size(), img.type());
while (1)
{
c = waitKey(100);
if (c == 27)
{
break;
}
else if (c == '1')
{
cvtColor(img, dst, COLOR_BGR2HSV);
}
else if (c == '2')
{
cvtColor(img, dst, COLOR_BGR2GRAY);
}
imshow("dst", dst);
}
}
三行代碼,讓opencv給我創建了十九個顏色表(
applyColorMap
void QuickDemo::color_style_demo(Mat& img)
{
int colormap[] = {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_HSV,
COLORMAP_PINK,
COLORMAP_HOT,//index:0-11
};
Mat dst;
int index = 0;
while (1)
{
char c;
c = waitKey(200);
if (c == 27)
{
break;
}
applyColorMap(img, dst, colormap[(index%11)]);
index++;
imshow("dst", dst);
}
}
影像像素的邏輯操作(位操作)
基本是就是對影像中的每一個像素點的灰度值進行和與或異或操作,
void QuickDemo::bitwises_demo(Mat& img)
{
//首先演示的是一個填充矩形的演算法
//講解如何使用opencv的函式進行繪制矩形
Mat drawer1 = Mat::zeros(Size(256, 256), CV_8UC3);
Mat drawer2 = Mat::zeros(Size(256, 256), CV_8UC3);
//呼叫api進行矩形的繪制
//api引數:(被畫的影像,要畫的矩形的規格Rect(左上角的x坐標,左上角的y坐標,row,col),矩形的顏色是什么Scalar(255,255,0),繪制的線的寬度,如果是小于0的時候就代表不畫線,填充該區域,產生鋸齒時的辦法(LINE_8,LINE_4,LINE_AA(反鋸齒等)),)
rectangle(drawer1, Rect(100, 100, 100, 100), Scalar(255, 255, 0), -1, LINE_8,0);
rectangle(drawer2, Rect(150, 150, 80, 80), Scalar(0, 255,255), -1, LINE_8,0);
imshow("drawer1", drawer1);
imshow("drawer2", drawer2);
Mat dst;
bitwise_and(drawer1,drawer2,dst);
//api引數:(輸入影像,輸入影像,輸出影像)
bitwise_or(drawer1, drawer2, dst);
bitwise_not(drawer1, dst);
//test-api
imshow("dst", dst);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293866.html
標籤:AI
