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通道彩色图像

  • flags=0返回灰度图像

  • flags<0返回包含Alpha通道的加载图像

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]

  • 如果图像是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_NORMAL

  • WINDOW_AUTOSIZE——窗口大小自适应,用户不能改变CV_WINDOW_AUTOSIZE

  • WIDNOW_OPENGL——窗口支持OPENGL CV_WINDOW_OPENGL

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)默认值是95

  • 对于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)));//随机颜色
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值