OpenCV 4.1.1 基础(C++)

OpenCV4.1.1 基础
一些基础图片处理代码

一、图像的读取、显示、窗口的命名、新建Mat对象的几种方法、掩膜处理。

#include<opencv2/opencv.hpp>//OpenCV头文件
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
    
    
    Mat a = imread("C:/Users/Lenovo/Desktop/新建文件夹/ConsoleApplication2/智能窗户logo.png");//新建一个Mat对象
    namedWindow("输出1", WINDOW_AUTOSIZE);//命名一个叫"输出1"的窗口,第二个参数表示窗口大小调整但不能手动改变窗口大小
    imshow("输出1", a);//显示图像在窗口"输出1"

    Mat b;
    b.create(a.size(), a.type());//新建Mat对象新方法
    b = Scalar(0, 0, 0);//此时b为黑色
    namedWindow("输出2", WINDOW_NORMAL);//第二个参数表示可以手动改变窗口大小
    imshow("输出2", b);

    Mat c(300, 300, CV_8UC1, Scalar(127));//第三个参数决定了这是一个单通道灰度图像
    namedWindow("输出3", WINDOW_AUTOSIZE);
    imshow("输出3", c);

    Mat qq;
    Mat cc = (Mat_<float>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
    filter2D(a, qq, -1, cc);//掩膜处理
    namedWindow("output", WINDOW_AUTOSIZE);
    imshow("output", qq);

    Mat d;
    d.create(a.size(), a.type());
    bitwise_not(a, d);//函数作用是图像取反
    //imshow("output", d);

    waitKey(0);//加上这个窗口不会一闪而过,参数是显示的毫秒数,如果参数为0则窗口无限等待
               //该函数返回值为摁键的ASCII码数值,如果没有摁键返回-1
    return 0;
}
图像c的第3个参数 CV_8UC1 为图像的预定义,预定义的结构为
CV_<bit_depth>(S|U|F)C<number_of_channels>
①–bit_depth—比特数—代表8bite,16bites,32bites,64bites—举个例子吧–比如说,如
如果你现在创建了一个存储–灰度图片的Mat对象,这个图像的大小为宽100,高100,那么,现在这张
灰度图片中有10000个像素点,它每一个像素点在内存空间所占的空间大小是8bite,8位–所以它对应的就是CV_8
②–S|U|F–S–代表—signed int—有符号整形
U–代表–unsigned int–无符号整形
F–代表–float---------单精度浮点型
③–C<number_of_channels>----代表—一张图片的通道数,比如:
1–灰度图片–grayImg—是–单通道图像
2–RGB彩色图像---------是–3通道图像
3–带Alpha通道的RGB图像–是–4通道图像

二、两个图像的按比例混合、相加、相乘。

图像的混合原理

在这里插入图片描述

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

int main()
{
    
    
    Mat src1 = imread("C:/Users/Lenovo/Desktop/新建文件夹/ConsoleApplication3/智能窗户logo1.png");
    Mat src2 = imread("C:/Users/Lenovo/Desktop/新建文件夹/ConsoleApplication3/智能窗户logo2.png");
    if (!src1.data)//新的判断图像是否读取成功的方法
    {
    
    
        cout << "could not load 智能窗户logo1...";
        return -1;
    }
    if (!src2.data)
    {
    
    
        cout << "could not load 智能窗户logo2...";
        return -1;
    }
    int height = src1.rows;//得到高度
    int width = src1.cols;//得到宽度
    cout << height << "   " << width << endl;

    //两个图像按比例混合
    if (src1.rows == src2.rows && src1.cols == src2.cols)
    {
    
    
        Mat dst;//混合后的图像为dst
        double alpha = 0.4;
        //addWeighted(src1, alpha, src2, 1 - alpha, 0.0, dst);
        //add(src1, src2, dst, Mat());//这个函数只是单纯的像素相加
        multiply(src1, src2, dst, 1.0);//像素相乘
        namedWindow("智能窗户logo1", WINDOW_AUTOSIZE);
        namedWindow("智能窗户logo2", WINDOW_AUTOSIZE);
        namedWindow("混合logo", WINDOW_AUTOSIZE);

        imshow("智能窗户logo1", src1);
        imshow("智能窗户logo2", src2);
        imshow("混合logo", dst);
    }
    else
    {
    
    
        cout << "could not blend images,the size of images is not same...";
        return -1;
    }

    waitKey(0);
    return 0;
}

三、调整图像亮度和对比度

图像变换可以看作是:
像素变换—点操作
邻域操作—区域
调整图像亮度和对比度为点操作,原理如下

在这里插入图片描述

每个像素点肯定是越靠近255亮度越高
saturate_cast(value) 确保值大小为范围为0~255
Mat.at(y,x)(index) =value 给每个像素点每个通道赋值
Mat dst_k = Mat::zeros(image.size(), image.type());新建一个与原图像大小类型相同的空白图像、像素值初始化为0。
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
    
    
    Mat src1 = imread("C:/Users/Lenovo/Desktop/新建文件夹/ConsoleApplication3/lly.jpg");
    if (!src1.data)
    {
    
    
        cout << "image could not load..." << endl;
        return -1;
    }
    string out_put_window = "output";
    int height = src1.rows;
    int width = src1.cols;
    float alpha = 1.2;
    int beta = 30;
    Mat dst_k = Mat::zeros(src1.size(), src1.type());//新建一个与原图像大小类型相同的空白图像、像素值初始化为0
    for (int row = 0; row < height; row++)
    {
    
    
        for (int col = 0; col < width; col++)
        {
    
    
            if (src1.channels() == 3)//如果是三通道图像
            {
    
    
                float b = src1.at<Vec3b>(row, col)(0);//blue
                float g = src1.at<Vec3b>(row, col)(1);//green
                float r = src1.at<Vec3b>(row, col)(2);//red

                //output
                dst_k.at<Vec3b>(row, col)(0) = saturate_cast<uchar>(alpha * b + beta);
                dst_k.at<Vec3b>(row, col)(1) = saturate_cast<uchar>(alpha * g + beta);
                dst_k.at<Vec3b>(row, col)(2) = saturate_cast<uchar>(alpha * r + beta);
            }
            else if (src1.channels() == 1)//如果是单通道图像
            {
    
    
                float v = src1.at<uchar>(row, col);
                dst_k.at<uchar>(row, col) = saturate_cast<uchar>(alpha * v + beta);
            }
        }
    }
    namedWindow("before", WINDOW_AUTOSIZE);
    imshow("before", src1);

    namedWindow(out_put_window, WINDOW_AUTOSIZE);
    imshow(out_put_window, dst_k);


    waitKey(0);
    return 0;
}

四、绘制文本和图形

图形中有直线、圆形、椭圆形、矩形、多边形、随机直线等。
相关API:
生成正态分布随机数 uniform(int a,int b)
生成高斯随机数 gaussian(double sigma)
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat src;
void myline();
void myRectangle();
void myEllipse();
void mycircle();
void myPolygon();
void Randomlinedemo();
int main()
{
    
    
    src = imread("C:/Users/Lenovo/Desktop/新建文件夹/ConsoleApplication3/lly.jpg");
    if (!src.data)
    {
    
    
        cout << "image could not load..." << endl;
        return -1;
    }
    string out_put_window = "output";
    myline();
    myRectangle();
    myEllipse();
    mycircle();
    myPolygon();
    putText(src, "HELLO WORLD!", Point(200, 100), FONT_HERSHEY_COMPLEX, 1.0, Scalar(12, 23, 255), 2, 8);
    //绘制文字函数原型,第一个参数是图像
    Randomlinedemo();

    namedWindow(out_put_window, WINDOW_AUTOSIZE);
    imshow(out_put_window, src);

    waitKey(0);
    return 0;
}
void myline()//线段
{
    
    
    Point p1 = Point(20, 30);
    Point p2;
    p2.x = 400;
    p2.y = 300;
    Scalar color = Scalar(0, 0, 225);
    line(src, p1, p2, color, 1, LINE_8);//绘制直线函数(图像,起始点,终止点,颜色,粗细,8连通)
}

void myRectangle()//正方形
{
    
    
    Rect rect_a = Rect(200, 100, 300, 300);
    Scalar color = Scalar(255, 0, 0);
    rectangle(src, rect_a, color, 1, LINE_8);
}
void myEllipse()//椭圆
{
    
    
    Scalar color = Scalar(0, 255, 0);
    ellipse(src, Point(src.rows / 2, src.cols / 2), Size(src.rows / 4, src.cols / 8), 90, 0, 360, color, 2, LINE_8);
    //椭圆(图像,原点,长半轴短半轴,旋转度数,从多少度开始,到多少度结束,颜色,粗细,8连通)
}
void mycircle()//园
{
    
    
    Scalar color = Scalar(0, 255, 255);
    circle(src,Point(500,500),200,color,3,LINE_8);
}
void myPolygon()//多边形
{
    
    
    Point pts[1][5];
    pts[0][0] = Point(100, 100);
    pts[0][1] = Point(100, 200);
    pts[0][2] = Point(200, 200);
    pts[0][3] = Point(200, 100);
    pts[0][4] = Point(100, 100);

    const Point* ppts[] = {
    
     pts[0] };
    int npt[] = {
    
     5 };
    Scalar color = Scalar(255, 255, 0);

    fillPoly(src, ppts, npt, 1, color, 8);//画填充
}
void Randomlinedemo()//随机线
{
    
    
    RNG rng(12345);
    Point p1;
    Point p2;
    Mat py = Mat::zeros(src.size(), src.type());//新建一个大小类型与src相同,一个黑色空白图像。
    namedWindow("py", WINDOW_AUTOSIZE);
    for (int i = 0; i < 100; i++)
    {
    
    
        p1.x = rng.uniform(0, src.rows);//生成正态分布随机数字
        p2.x = rng.uniform(0, src.rows);
        p1.y = rng.uniform(0, src.cols);
        p2.y = rng.uniform(0, src.cols);
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        line(py, p1, p2, color, 1, 8);
        if (waitKey(50) > 0)
        {
    
    
            break;
        }
        imshow("py", py);
    }

}

猜你喜欢

转载自blog.csdn.net/Huo6666/article/details/107519423