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的源码整理出来。。。