opencv4学习笔记

demo1

点击查看代码
	//2021.6.2
	//(第二个参数设置成IMREAD_GRAYSCALE就是灰度图像,其他效果可设置第二个标志参数)
	Mat img = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\3.png");
	namedWindow("img", WINDOW_FREERATIO);//可调整大小

	/*
	默认窗口标志是WINDOW_AUTOSIZE,即原图像大小
	imshow只支持8位(即256)的显示和浮点数数据的显示,如果是其他格式的数据则可能出现错误
	*/
	imshow("img", img);

	Mat hsv, gray;

	/*
	 bgr转hsv
	 bgr每一个有8位,总共24位,0~255,再加上透明度,总共有4个256,256*256*256*256,pow(2,32)
	 hsv,h:0~180,s、v:0~255,h、s表示颜色,s可以调整饱和度,v可以调亮度 
	 bgr其实就是rgb,8位rgb通道的顺序为b、g、r(读进来的彩色图像)
	*/
	cvtColor(img, hsv, COLOR_BGR2HSV);

	cvtColor(img, gray, COLOR_BGR2GRAY);
	imshow("hsv", hsv);
	imshow("gray", gray);
	imwrite("C:\\Users\\AIT\\Pictures\\Saved Pictures\\3hsv.png", hsv);//保存图片

	waitKey();//使窗口阻塞,图片窗口一直显示
	destroyAllWindows();

demo2

点击查看代码
	//2021.6.3
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");

	//制作空白图像
	Mat green,white;
	green = src.clone();//深拷贝(直接赋值就是浅拷贝)
	src.copyTo(white);//深拷贝
	green = Mat::zeros(Size(512, 512), CV_8UC3);//填充0,512*512,8位 unsigned char,3通道
	white = Mat::ones(Size(512, 512), CV_8UC1);//填充1,单通道
	cout << "cols:" << green.cols << "\n";//宽度
	cout << "rows:" << green.rows << "\n";//高度
	cout << "channels:" << green.channels() << "\n";//通道数
	//cout << green << endl;
	green = Scalar(0, 255, 0);//b、g、r(3通道),变成绿色了
	white = Scalar(255);//单通道,变成白色了
	imshow("green", green);
	imshow("white", white);

demo3

点击查看代码
	//2021.6.4
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
	imshow("srcOld", src);

	/*
	图像像素读写
	*/

	int nRows = src.rows;
	int nCols = src.cols;
	int nChannels = src.channels();
	
	//数组的方式
	//for (int row = 0; row < nRows; row++)
	//{
	//	for (int col = 0; col < nCols; col++)
	//	{
	//		if (nChannels == 1)//灰度图像,单通道
	//		{
	//			int nPx = src.at<uchar>(row, col);
	//			src.at<uchar>(row, col) = 255 - nPx;
	//		}
	//		else if (nChannels == 3)//彩色图像,3通道
	//		{
	//			Vec3b bgr = src.at<Vec3b>(row, col);
	//			src.at<Vec3b>(row, col)[0] = 255 - bgr[0];
	//			src.at<Vec3b>(row, col)[1] = 255 - bgr[1];
	//			src.at<Vec3b>(row, col)[2] = 255 - bgr[2];
	//		}
	//	}
	//}

	//指针的方式(更快)
	for (int row = 0; row < nRows; row++)
	{
		uchar* currentRow = src.ptr<uchar>(row);
		for (int col = 0; col < nCols; col++)
		{
			if (src.channels() == 1)//单通道
			{
				*currentRow++ = 255 - *currentRow;
			}
			else if (src.channels() == 3)//3通道
			{
				*currentRow++ = 255 - *currentRow;
				*currentRow++ = 255 - *currentRow;
				*currentRow++ = 255 - *currentRow;
			}
		}
	}

	imshow("srcNew", src);

demo4

点击查看代码
	//2021.6.5
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
	imshow("srcOld", src);

	/*
	图像像素算术运算
	*/

	int nRows = src.rows;
	int nCols = src.cols;
	int nChannels = src.channels();

	Mat temp = src + Scalar(50, 50, 50);//变亮了
	temp = src - Scalar(50, 50, 50);//变暗了
	temp = src / Scalar(2,2,2);
	
	//可以直接使用opencv提供的API
	temp = Mat::zeros(src.size(), src.type());
	temp = Scalar(50, 50, 50);
	Mat ret;
	add(src, temp, ret);//加
	subtract(src, temp, ret);//减
	multiply(src, temp, ret);//乘
	divide(src, temp, ret);//除

	for (int row = 0; row < nRows; row++)
	{
		for (int col = 0; col < nCols; col++)
		{
			Vec3b p1 = src.at<Vec3b>(row, col);
			Vec3b p2 = temp.at<Vec3b>(row, col);

			//saturate_cast<uchar>(...),使得括号里面计算出来的结果在uchar范围之内,小于0则取0,大于255则取255
			ret.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0]+p2[0]);
			ret.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1]+p2[1]);
			ret.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2]+p2[2]);
		}
	}

	imshow("srcNew", ret);

demo5

点击查看代码
void callBack(int nPos,void*src)//第一个参数是滚动条的位置
{
	Mat temp;
	temp = *(Mat*)src + Scalar(nPos, nPos, nPos);
	imshow("srcNew",temp);
}

void adjustContrast(int nPos,void*src)//调整对比度(亮的地方更亮,暗的地方更暗)
{
	Mat img = *(Mat*)src;
	Mat ret = Mat::zeros(img.size(), img.type());
	Mat sec=Mat::zeros(img.size(),img.type());
	//sec = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\7.jpg");
	//resize(img, sec, img.size());//把sec调整到和img一样大
	double alpha = nPos / 50.0;
	double beta = 0.0;
	double gamma = nPos;

	//ret=img*alpha+sec*beta+gamma,gamma表示要增加多少亮度,如果传0则只关注对比度,不关注亮度
	addWeighted(img, alpha, sec, beta, gamma, ret);

	imshow("srcNew", ret);
}

int main()
{
	//2021.6.5
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
	imshow("srcOld", src);

	/*
	创建Trackbar滚动条来调整亮度
	*/

	int nRows = src.rows;
	int nCols = src.cols;
	int nChannels = src.channels();

	int nLightness = 50;
	int nMax = 100;
	namedWindow("srcNew");
	createTrackbar("start", "srcNew", &nLightness,nMax,callBack,&src);
	createTrackbar("contrast", "srcNew", &nLightness, nMax, adjustContrast, &src);

	waitKey();//使窗口阻塞,图片窗口一直显示
	destroyAllWindows();

	return 0;
}

demo6

点击查看代码
	//2021.6.5
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
	imshow("srcOld", src);

	/*
	监听键盘事件
	*/

	int nRows = src.rows;
	int nCols = src.cols;
	int nChannels = src.channels();

	Mat temp = Mat::zeros(src.size(), src.type());
	while (true)
	{
		int nRes = waitKey(100);
		if (nRes == 27)//按下了ESC键,ASCII码值
		{
			break;
		}
		else if (nRes == 49)//按下了1
		{
			cvtColor(src, temp, COLOR_BGR2GRAY);//bgr转灰度图像
		}
		else if (nRes == 50)//按下了2
		{
			cvtColor(src, temp, COLOR_BGR2HSV);
		}
		imshow("srcNew", temp);
	}

demo7

点击查看代码
	//2021.6.5
	Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
	imshow("srcOld", src);

	/*
	颜色表
	*/

	int nRows = src.rows;
	int nCols = src.cols;
	int nChannels = src.channels();

	Mat temp = Mat::zeros(src.size(), src.type());

    //ColormapTypes枚举中的值
    int nColorMapArray[] =
    {
        COLORMAP_AUTUMN,//0
        COLORMAP_BONE,
        COLORMAP_JET,
        COLORMAP_WINTER ,
        COLORMAP_RAINBOW ,
        COLORMAP_OCEAN ,
        COLORMAP_SUMMER,
        COLORMAP_SPRING,
        COLORMAP_COOL ,
        COLORMAP_HSV,
        COLORMAP_PINK ,
        COLORMAP_HOT ,
        COLORMAP_PARULA,
        COLORMAP_MAGMA ,
        COLORMAP_INFERNO ,
        COLORMAP_PLASMA ,
        COLORMAP_VIRIDIS,
        COLORMAP_CIVIDIS,
        COLORMAP_TWILIGHT ,
        COLORMAP_TWILIGHT_SHIFTED ,
        COLORMAP_TURBO ,
        COLORMAP_DEEPGREEN//21
    };

    int nIndex = 0;
    while (true)
    {
        int nCode = waitKey(500);
        if (nCode == 27)//按下ESC就退出
        {
            break;
        }

        applyColorMap(src, temp, nIndex++ % (sizeof(nColorMapArray) / sizeof(nColorMapArray[0])));//范围在0~21之间
        imshow("srcNew", temp);
    }

demo8

点击查看代码
    //2021.6.7
    Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\peace.jpg");
    imshow("srcOld", src);

    /*
    像素位运算
    */

    Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
    Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3);

    /*
    创建矩形,第四个参数小于0则表示填充,大于等于0表示描边不填充
    LINE_AA反锯齿,但会影响速度,所以一般用LINE_8,不关心锯齿  
    */
    rectangle(m1, Rect(50, 50, 100, 100), Scalar(255, 0, 0), -1, LINE_8, 0);
    rectangle(m2, Rect(50, 50, 100, 100), Scalar(0, 255, 0), -1, LINE_8, 0);

    bitwise_and(m1, m2, src);//与
    bitwise_or(m1, m2, src);//或
    bitwise_not(src, src);//非
    bitwise_xor(m1, m2, src);//异或
    src = ~src;//取反,也是非的意思,但是可读性差

    imshow("m1", m1);
    imshow("m2", m2);
    imshow("srcNew", src);

demo9

点击查看代码
    //2021.6.20
    Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\20201108.jpg");
    namedWindow("srcOld", 0);
    resizeWindow("srcOld", 700, 500);
    imshow("srcOld", src);

    /*
    通道分离与合并
    */

    /*namedWindow("blue", 0);
    namedWindow("green", 0);
    namedWindow("red", 0);*/
    namedWindow("onlyBlue", 0);
    namedWindow("mix", 0);
    /*resizeWindow("blue", 700, 500);
    resizeWindow("green", 700, 500);
    resizeWindow("red", 700, 500);*/
    resizeWindow("onlyBlue", 700, 500);
    resizeWindow("mix", 700, 500);

    vector<Mat>dst;
    split(src, dst);//通道分离

    //通道输出顺序为bgr,输出灰度图像
    /*imshow("blue",dst[0]);
    imshow("green", dst[1]);
    imshow("red", dst[2]);*/

    //把g、r通道置0,剩下b通道,只显示蓝色
    //也可试试其他效果,比如只把某一个通道置0,合并其余两个通道
    Mat ret;
    //dst[0] = 0;
    //dst[2] = 0;
    merge(dst, ret);//通道合并
    imshow("onlyBlue", ret);

    /*
    把src通道0赋给ret通道1,把src通道1赋给ret通道2,把src通道2赋给ret通道0
    等同于
    {
        vector<Mat>dst1,dst2;
        split(src,dst1);
        split(src,dst2);
        dst1[1]=dst2[0];
        dst1[2]=dst2[1];
        dst1[0]=dst2[2];
        Mat ret;
        merge(dst1,ret);
    }
    */
    int fromTo[] = {0,1,1,2,2,0};
    //参数:数值1表示mat的数量,数值3表示有3对(即fromTo数组里面的3对,[0,1],[1,2],[2,0])
    mixChannels(&src, 1, &ret, 1, fromTo, 3);//混合通道
    imshow("mix", ret);

demo10

点击查看代码
    //2021.6.24
    Mat src = imread("C:\\Users\\AIT\\Pictures\\Saved Pictures\\fish.jpg");
    namedWindow("srcOld", 0);
    resizeWindow("srcOld", 500, 313);
    imshow("srcOld", src);

    namedWindow("srcMask", 0);
    resizeWindow("srcMask", 500, 313);

    /*
    图像色彩空间转换,提取轮廓等
    */
    
    /*在rgb空间里很难提取正确的像素值,因为分布很广,r、g、b再加上透明度,总共2的32次方
    而在hsv空间里只有h、s这两个控制颜色的,相对容易进行提取(色彩辨识度比较高)*/

    Mat hsv;
    cvtColor(src, hsv, COLOR_BGR2HSV);//转成hsv图像
    Mat mask;
    //hsv色彩空间里黑色的最小值和黑色的最大值,这样设置的话黑色就会变成白色,非黑色就会变成黑色
    inRange(hsv, Scalar(0, 0, 0), Scalar(180, 255, 46), mask);
    imshow("srcMask", mask);

    Mat orange = Mat::zeros(src.size(), src.type());
    orange = Scalar(15, 196, 241);
    //将mask取反,使得黑色部分(像素值为0)的轮廓变成白色(像素值为1),可以被提取出来(像素为1的部分可以被编辑拷贝)
    bitwise_not(mask, mask);
    src.copyTo(orange, mask);
    imshow("orangeBgc", orange);

运行结果:

hsv色彩空间:

还在学习中,等把基础学完了就会把所有demo的源码整理出来。。。

 

posted @ 2021-06-06 10:08  youlj  阅读(89)  评论(0编辑  收藏  举报