OpenCV 學習筆記1

來 源 《OpenCV3 編程入門》

opencv 版本2.8.4

1 imread函數

Mat imread (const string& filename, int flags = 1);

1 filename:要載入的圖片路徑名

2 fiags爲載入標識,指定一個加載圖像的顏色類型,默認值爲1,表示載入三通道的彩色圖像。這個參數能夠在OpenCV中標識圖像格式的枚舉體中取值。若爲0,灰度圖像。若爲2:當載入圖像的深度爲16位或者32位,返回對應深度的圖像,不然轉換爲8位圖像再返回。

3由於flags是int類型獲得變量,若不在枚舉體裏取固定的值,能夠這樣進行:

  • flags>0 返回一個3通道彩色圖像c++

  • flags=0返回灰度圖像編程

  • flags<0返回包含Alpha通道的加載圖像ide

4 注意:若以彩色模式載入圖像,解碼後的圖像會以BGR的通道進行存儲,即藍,綠,紅的順序,不是一般的RGB順序。

Mat image0 = imread("1.jpg", 2|4) ;//載入無損的原圖像
Mat image1 = imread("1.jpg", 0);//載入灰度圖
Mat image2 = imread("1.jpg", 199);//載入3通道的彩色圖像

2 imshow函數

void imshow (const string& winname, InputArray mat);

1 winname:填須要顯示的窗口標識名稱。

2 mat:須要顯示的圖像

  • 若是載入圖像是8位無符號類型,就顯示圖像原本的樣子函數

  • 若是圖像是16位無符號類型或32位整型,用像素值除以256,值的範圍是[0, 256x256]映射到[0, 255]ui

  • 若是圖像是32位浮點型,像素值要乘以255.該值的範圍是[0, 1]映射到[0, 255]。編碼


3 namedWindow()函數

void namedWindow(const string& winname, int flags = WINDOW_AUTOSIZE);

1 name:窗口名字

2 flags:窗口標識

  • WINDOW_NORMAL——用戶能夠改變窗口大小(沒有限制)CV_WINDOW_NORMALspa

  • WINDOW_AUTOSIZE——窗口大小自適應,用戶不能改變CV_WINDOW_AUTOSIZE指針

  • WIDNOW_OPENGL——窗口支持OPENGL CV_WINDOW_OPENGLcode

3 能夠用destroyWindow()函數來關閉窗口,不經常使用


4. imwrite()函數

bool imwrite(const string& filename, InputArray img, const vector<int>& params = vector<int>());

1 filename:要寫入的文件名

2 img:填一個mat類型的圖像數據

3 params,表示爲特定格式保存的編碼,通常狀況下,不須要填寫。

  • 對於JPEG格式的圖片,這個參數表示從0到100的圖片質量(CV_IMWRITE_JPEG_QUALITY)默認值是95orm

  • 對於png格式,這個參數表示壓縮級別(CV_IMWRITE_PNG_COMPRESSION)從0到9,較高值覺得值更小的尺寸和更長的壓縮時間,默認值3

  • 對於ppm,pgm,或pbm格式的圖片,這個參數表示一個二進制格式標誌(CV_IMWRITE_PXM_BINARY)取值爲0或1, 默認值是1


5. 滑動條的建立和使用

1 createTrackbar()函數

int createTrackbar(const string& trackbarname, const string& winname, int *value, int count, TrackbarCallback onChange = 0, void* userdata = 0);
  • trackbarname:軌跡條的名字

  • winname:窗口的名字,表示這個軌跡條會依附到那個窗口上、

  • value:指向int的指針,表示滑塊的位置,滑塊的初試位置就是該變量當前的值。

  • count:表示滑塊能夠達到的最大位置的值。滑塊最小位置始終爲0

  • trackbarcallback類型的onchange,它有默認值爲0.這是一個指向回調函數的指針,每次滑塊位置改變時,這個函數都會進行回調。而且這個函數的原型必須爲void xxxx(int, void*) 其中,第一個參數是軌跡條的位置,第二個參數是用戶數據,若是回調是null指針,則表示沒有回調函數的調用,僅第三個參數value有變化。

  • userdata也有默認值0, 這個從參數是用戶傳給回調函數的數據,用來處理軌跡條事件。若是使用的第三個參數value實參是全局變量的話,能夠不用管這個參數。

2 getTrackbarPos()函數--用於獲取當前軌跡條的位置

int getTrackbarPos(const string& trackbarname, const string& winname);
  • trackbarname:軌跡條的名字

  • winname:軌跡條父窗口的名稱

6 鼠標操做

SetMouseCallback函數的做用是爲指定的窗口設置鼠標回調函數,原型以下:

void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);

1 winname:窗口名字

2 onMouse:指定窗口裏每次鼠標事件發生的時候,被調用的函數指針。這個函數的原型的大概形式爲

void Foo(int event, int x, int y, int flags, void *param)
其中event是EVENT_+變量之一,x和y是鼠標指針在圖像座標系(不是窗口座標系)中的座標值,flags是EVENT_FLAG的組合,param是用戶定義的傳遞到setmousecallback函數調用的參數。如EVENT_MOUSEMOVE爲鼠標移動消息、EVENT_LBUTTONDOWN爲鼠標左鍵按下消息。

3 userdata:有默認值0.

代碼示例

1 圖像腐蝕

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc//imgproc.hpp>
using namespace cv;

int main_2()
{
    Mat srcImage = imread("pic.jpg");
    imshow("[原圖]腐蝕操做", srcImage);
    Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
    Mat dstImage;
    erode(srcImage, dstImage, element);
    imshow("[效果圖]腐蝕操做", dstImage);
    waitKey(0);
    return 0;
}

2 模糊

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;


int main_3()
{
    Mat srcImage = imread("pic.jpg");
    imshow("均值濾波【原圖】", srcImage);
    Mat dstImage;
    blur(srcImage, dstImage, Size(7, 7));
    imshow("均值濾波【效果圖】", dstImage);
    waitKey(0);
    return 0;
}

3 邊緣檢測

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;

int main_4()
{
    Mat srcImage = imread("pic.jpg");
    imshow("【原始圖】Canny邊緣檢測", srcImage);
    Mat dstImage, edge, grayImage;
    dstImage.create(srcImage.size(), srcImage.type());//建立與src同類型和大小的矩陣
    //將原圖像轉換爲灰度圖像
    cvtColor(srcImage, grayImage, CV_BGR2GRAY);//opecv2 代碼版本
    blur(grayImage, edge, Size(3, 3));
    Canny(edge, edge, 3, 9, 3);
    imshow("【效果圖】Canny邊緣檢測", edge);
    waitKey(0);
    return 0;
}

//不知道這裏的dstImage是幹什麼的

4 使用攝像頭

#include <opencv2/opencv.hpp>
using namespace cv;

// int main()
// {
//     //VideoCapture capture("1.avi");//讀取視頻
//     VideoCapture capture(0);//調取攝像頭
//     while(1)
//     {
//         Mat frame;
//         capture >> frame;
//         imshow("讀取視頻", frame);
//         waitKey(1);
//     }
//     return 0;
// }

int main_5()
{
    VideoCapture capture(0);
    Mat edges;
    while(1)
    {
        Mat frame;
        capture >> frame;
        cvtColor(frame, edges, CV_BGR2GRAY);
        blur(edges, edges,Size(7, 7));
        Canny(edges, edges, 0, 30, 3);
        imshow("Canny後的視頻", edges);
        if (waitKey(30) >= 0)
        {
            break;
        }
    }
    return 0;
}

5 imwrite使用

#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <vector>

using namespace std;
using namespace cv;

void creatAlphaMat(Mat &mat)
{
    for (int i = 0; i < mat.rows; ++i)
    {
        for (int j = 0; j < mat.cols; ++j)
        {
            Vec4b &rgba = mat.at<Vec4b>(i, j);
            rgba[0] = UCHAR_MAX;
            rgba[1] = saturate_cast<uchar>((float(mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);
            rgba[2] = saturate_cast<uchar>((float(mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX);
            rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2]));
        }
    }
}

int main_6()
{
    Mat mat(480, 640, CV_8UC4);
    creatAlphaMat(mat);//建立帶Alpha通道的mat

    vector<int>compression_params;
    //compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);//書中寫這句是v2的下面兩句是v3的,可是這裏庫是v248的,要是用下面的代碼才能運行成功
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    
    try
    {
        imwrite("透明Alpha值圖.png", mat, compression_params);
        imshow("生成的png圖", mat);
        fprintf(stdout, "png圖片文件的alpha數據保存完畢~\n 能夠在工程目錄下查看由imwrite函數生成的圖片\n");
        waitKey(0);
    }
    catch(runtime_error& ex)
    {
        fprintf(stderr, "圖像轉換成png格式發生錯誤:%s\n", ex.what());
        return 1;
    }
    return 0;
}

6 混合

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int main_7()
{
    Mat girl = imread("girl.jpg");
    namedWindow("[1]動漫圖");
    imshow("[1]動漫圖", girl);

    Mat image = imread("dota.jpg", 199);
    Mat logo = imread("dota_logo.jpg");
    namedWindow("[2]原畫圖");
    imshow("[2]原畫圖", image);
    
    namedWindow("[3]logo圖");
    imshow("[3]logo圖", logo);

    Mat imageROI;
    imageROI = image(Rect(800, 350, logo.cols, logo.rows));

    addWeighted(imageROI, 0.5, logo, 0.3, 0., imageROI);

    namedWindow("[4]原畫+logo圖");
    imshow("[4]原畫+logo圖", image);

    imwrite("由imwrite生成的圖片.jpg", image);

    waitKey(0);
    return 0;

}

7 進度條

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"

using namespace cv;

#define WINDOW_NAME "【線性混合示例】"

const int g_nMaxAlphaValue = 100; //alpha 的最大值
int g_nAlphaValueSlider;//滑動條對應的變量
double g_dAlphaValue;
double g_dBetaValue;

Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

void on_Trackbar(int , void*)
{
    //求出當前alpha值相對於最大值的比例
    g_dAlphaValue = (double) g_nAlphaValueSlider / g_nMaxAlphaValue;
    //beta值爲1-Alpha
    g_dBetaValue = (1.0 - g_dAlphaValue);
    //根據alpha和beta進行線性混合
    addWeighted(g_srcImage1, g_dAlphaValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);
    imshow(WINDOW_NAME, g_dstImage);
}

int main_8()
{
    g_srcImage1 = imread("1.jpg");
    g_srcImage2 = imread("2.jpg");

    if (!g_srcImage1.data)
    {
        printf("讀取第一幅圖片錯誤,請肯定目錄下是否有imread函數指定的圖片存在~!\n");
        return -1;
    }
    if (!g_srcImage2.data)
    {
        printf("讀取第二幅圖片錯誤,請肯定目錄下是否有imread函數指定的圖片存在~!\n");
        return -1;
    }

    g_nAlphaValueSlider = 70;//滑動條初值爲70
    namedWindow(WINDOW_NAME, 1);

    char TrackbarName[50];
    sprintf(TrackbarName, "透明值 %d", g_nMaxAlphaValue);

    createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);

    on_Trackbar(g_nAlphaValueSlider, 0);
    

    waitKey(0);
    return 0;

}

8 鼠標操做

#include <opencv2/opencv.hpp>
using namespace cv;

#define WINDOW_NAME "【程序窗口】"

void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);
void ShowHelpText();

Rect g_rectangle;
bool g_bDrawingBox = false;//是否進行繪製
RNG g_rng(12345);

int main(int argc, char** argv)
{
    g_rectangle = Rect(-1, -1, 0, 0);
    Mat srcImage(600, 800, CV_8UC3), tempImage;
    srcImage.copyTo(tempImage);
    g_rectangle = Rect(-1, -1, 0, 0);
    srcImage = Scalar::all(0);

    namedWindow(WINDOW_NAME);
    setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);

    while (1)
    {
        srcImage.copyTo(tempImage);
        if (g_bDrawingBox)
        {
            DrawRectangle(tempImage, g_rectangle);
            //當進行繪製的標識符爲真,則進行繪製
        }
        imshow(WINDOW_NAME, tempImage);

        if (waitKey(10) == 27)//esc
        {
            break;
        }
    
    }
        return 0;
}
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
    Mat &image = *(cv::Mat*) param;
    switch(event)
    {
    case EVENT_MOUSEMOVE:
        {
            if (g_bDrawingBox)
            {
                g_rectangle.width = x - g_rectangle.x;
                g_rectangle.height = y - g_rectangle.y;
            }
        }
        break;
    case EVENT_LBUTTONDOWN:
        {
            g_bDrawingBox = true;
            g_rectangle = Rect(x, y, 0, 0);
        }
        break;

    case EVENT_LBUTTONUP:
        {
            g_bDrawingBox = false;
            if (g_rectangle.width < 0)
            {
                g_rectangle.x += g_rectangle.width;
                g_rectangle.width *= -1;
            }
            if (g_rectangle.height < 0)
            {
                g_rectangle.y += g_rectangle.height;
                g_rectangle.height *= -1;
            }

            DrawRectangle(image, g_rectangle);
        }
        break;
    }
}

void DrawRectangle(cv::Mat& img, cv:: Rect box)
{
    rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//隨機顏色
}
相關文章
相關標籤/搜索