文章目录
- 1、创建窗口
- 2、读取图片
- 3、视频采集
- 4、Mat的使用
- 5、异或操作
- 6、通道分离,通道合并
- 7、色彩空间转换
- 8、最大值、最小值
- 9、绘制图像
- 10、多边形绘制
- 11、随机数
- 12、鼠标实时绘制矩形
- 13、归一化
- 14、resize操作
- 15、旋转翻转
- 16、视频操作
- 17、模糊操作
- 18、高斯模糊操作
1、创建窗口
c++写法:
void test2()
{Mat img = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");cout<<img.depth()<<" "<<img.channels()<<endl;namedWindow("new",cv::WINDOW_AUTOSIZE);imshow("new",img);waitKey(0);destroyAllWindows();
}
python写法:
def test():cv2.namedWindow('new', cv2.WINDOW_NORMAL)cv2.imshow('new', 0)key = cv2.waitKey(0)if key & 0xFF == ord('q'):cv2.destroyAllWindows()
2、读取图片
c++写法,操作图像,将图像转换为hsv然后调整亮度值,转换会BGR格式显示
void test2()
{Mat img = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");cout<<img.depth()<<" "<<img.channels()<<endl;namedWindow("new",cv::WINDOW_AUTOSIZE);imshow("new",img);waitKey(0);Mat gray,hsv;cvtColor(img,gray,cv::COLOR_BGR2GRAY);imshow("new",gray);waitKey(0);cvtColor(img,hsv,cv::COLOR_BGR2HSV);imshow("new",hsv);waitKey(0);Mat channels[3];// 将HSV图像分离为三个单独的通道,这将把HSV图像的三个通道分别存储在channels数组的不同元素中split(hsv,channels);int bright = 50;channels[2] += bright;// 将亮度通道的像素值限制在0到255之间,大于255截断为255threshold(channels[2],channels[2],255,255,cv::THRESH_TRUNC);// 将修改后的通道合并为单个图像cv::merge(channels, 3, hsv);Mat outputImage;cv::cvtColor(hsv, outputImage, cv::COLOR_HSV2BGR);imshow("new",outputImage);waitKey(0);destroyAllWindows();
}
@param filename Name of file to be loaded.
@param flags Flag that can take values of cv::ImreadModesCV_EXPORTS_W Mat imread( const String& filename, int flags = IMREAD_COLOR );flags标识符介绍:
IMREAD_GRAYSCALE = 0, 灰度图
IMREAD_COLOR = 1,原本是什么颜色就显示什么颜色
def test2():cv2.namedWindow('new', cv2.WINDOW_AUTOSIZE)img = cv2.imread(img_name, 1)cv2.imshow('new', img)cv2.waitKey(0)cv2.destroyAllWindows()cv2.imwrite('1.png',img)
3、视频采集
def test3():# cv2.namedWindow('new', cv2.WINDOW_AUTOSIZE)# 获取视频设置 cap = cv2.VideoCapture(0)while True:ret, frame = cap.read()cv2.imshow('video', frame)key = cv2.waitKey(10)if (key & 0xFF) == ord('q'):breakcap.release()cv2.destroyAllWindows()
录制视频
def test4():fourcc = cv2.VideoWriter_fourcc(*'MJPG')vw = cv2.VideoWriter('./out.mp4', fourcc, 25, (1920, 1080))cap = cv2.VideoCapture(0)# 判断摄像头是否打开状态while cap.isOpened():ret, frame = cap.read()if ret == True:cv2.imshow('video', frame)# 写数据到多媒体文件vw.write(frame)key = cv2.waitKey(10)if (key & 0xFF) == ord('q'):breakelse:breakcap.release()cv2.release()cv2.destroyAllWindows()
import cv2# 色彩空间
# hsv:色相、饱和度、明亮度
# yuv:4:2:0 4:2:2 4:4:4def callback():passdef test7():cv2.namedWindow('color',cv2.WINDOW_NORMAL)img = cv2.imread('./1.png')colorspaces = [cv2.COLOR_BGR2RGBA,cv2.COLOR_BGR2BRGA,cv2.COLOR_BGR2GRAY,cv2.COLOR_BGR2HSV_FULLL,cv2.COLOR_BGR2YUV]cv2.createTrackbar('curcolor','color',0,len(colorspaces),callback)while True:index = cv2.getTrackbarPos('curcolor','color')cvt_img = cv2.cvtColor(img,colorspaces[index])cv2.imshow('color',img)key = cv2.waitKey(10)if key & 0xFF == ord('q'):breakcv2.destroyAllWindows()if __name__ == '__main__':test7()
4、Mat的使用
深拷贝和浅拷贝
void test3()
{Mat img,m1,m2;img = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");// 克隆,深拷贝m1 = img.clone();img.copyTo(m2);// 创建空白图像Mat m3 = Mat::zeros(Size(8,8),CV_8UC1);// 创建全部为1的通道,如果创建的是3通道,则只有每个元素的第一个通道为1Mat m4 = Mat::ones(Size(8,8),CV_8UC3);cout<<m3.cols<<m3.rows<<m3.channels()<<endl;// 3通道时候:每个元素的第一个通道为1m4 = 127;// 给3个通道都复值m4 = Scalar(127,127,127);
}
像素值操作:
1、根据下标操作
2、根据指针操作
void test4()
{// 像素遍历操作namedWindow("new",WINDOW_NORMAL);Mat img,gray;img = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");for(int i=0;i<img.rows;i++){for(int j=0;j<img.cols;j++){Vec3b bgr = img.at<Vec3b>(i,j);img.at<Vec3b>(i,j)[0] = 255 - bgr[0];img.at<Vec3b>(i,j)[1] = 255 - bgr[1];img.at<Vec3b>(i,j)[2] = 255 - bgr[2];}}imshow("new",img);waitKey(0);cvtColor(img,gray,cv::COLOR_BGR2GRAY);for(int i=0;i<gray.rows;i++){for(int j=0;j<gray.cols;j++){int pt = img.at<uchar>(i,j);img.at<uchar>(i,j) = 255 - pt;}}imshow("new",gray);waitKey(0);// 基于指针访问 速度更快for(int i=0;i<img.rows;i++){uchar *current_row = img.ptr<uchar>(i);for(int j=0;j<img.cols;j++){if(img.channels() == 1){int pt = *current_row;*current_row++ = 255 - pt;}else if(img.channels() == 3){*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;*current_row++ = 255 - *current_row;}}}destroyAllWindows();
}
像素值的加减乘除
void test5()
{// 像素操作namedWindow("new",WINDOW_NORMAL);Mat img,gray;img = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");Mat m = Mat::zeros(img.size(),img.type());m = Scalar(2,2,2);Mat dst;// 乘法运算,超过255的时候会截断multiply(img,m,dst);// 加法操作add(img,m,dst);// 减法subtract(img,m,dst);// 除法divide(img,m,dst);// saturate_cast会做一个范围判定,是否在uchar范围内// saturate_cast<uchar>(p1,p2);imshow("new",dst);waitKey(0);destroyAllWindows();
}
GUI操作
void on_trac(int val,void *userdata)
{Mat *data = (Mat*)userdata;Mat m = Mat::zeros(data->size(),data->type());m = Scalar(val,val,val);Mat dst;add(*data,m,dst);imshow("new",dst);
}void test6()
{namedWindow("new",WINDOW_AUTOSIZE);Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");int maxValue = 100;int light = 50;cout<<src.type()<<endl;createTrackbar("Value Bar","new",&light,maxValue,on_trac,(void *)(&src));on_trac(50,&src);
}
addWeighted函数解释
dst = src1 * alpha + src2 * beta + gamma
5、异或操作
// 异或操作
void test7()
{Mat m1 = Mat::zeros(Size(255,255), CV_8UC3);Mat m2 = Mat::zeros(Size(255,255), CV_8UC3);rectangle(m1,Rect(100,100,80,80),Scalar(255,255,0),-1,LINE_8,0);rectangle(m2,Rect(130,130,80,80),Scalar(255,0,255),-1,LINE_8,0);imshow("new",m1);waitKey(0);imshow("new",m2);waitKey(0);Mat dst;// 按位与(都为真就为真)bitwise_and(m1,m2,dst);imshow("new",dst);waitKey(0);// 按位或(一个为真就为真)bitwise_or(m1,m2,dst);imshow("new",dst);waitKey(0);// 按位取反bitwise_not(m1,dst);imshow("new",dst);waitKey(0);// 异或(不同为真,相同为假)bitwise_xor(m1,m2,dst);imshow("new",dst);waitKey(0);destroyAllWindows();
}
6、通道分离,通道合并
// 通道分离,通道合并
void test8()
{namedWindow("new",WINDOW_AUTOSIZE);Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");imshow("new",src);waitKey(0);vector<Mat> mv;split(src,mv);imshow("new",mv[0]);waitKey(0);imshow("new",mv[1]);waitKey(0);imshow("new",mv[2]);waitKey(0);// 将蓝色和绿色通道全部置0,只保留红色通道,然后合并mv[0] = 0;mv[1] = 0;Mat dst;merge(mv,dst);imshow("new",dst);waitKey(0);// 通道融合// 第三个参数,0通道到2通道,1通道到1通道,2通道到0通道int from_to[] = {0,2,1,1,2,0};mixChannels(&src,1,&dst,1,from_to,3);imshow("new",dst);waitKey(0);
}
7、色彩空间转换
// 色彩空间转换
void test9()
{namedWindow("new",WINDOW_AUTOSIZE);Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/green.jpg");Mat dst,mask;cvtColor(src,dst,COLOR_BGR2HSV);// 出来一张2值化的图像,绿色背景是白色,人物是黑色inRange(dst,Scalar(35,43,46),Scalar(77,255,255),mask);Mat redback = Mat::zeros(src.size(),src.type());redback = Scalar(40,40,200);// 取放之后人物酒变成白色了,背景是黑色的bitwise_not(mask,mask);// 只拷贝不为0的区域,为0的区域不拷贝src.copyTo(redback,mask);imshow("new",redback);waitKey(0);
}
8、最大值、最小值
// 最大值、最小值
// 均值,方差
// 方差衡量数据集中值的离散程度,数据集中差异较小时,标准方差较小,差异较大时,方差较大(携带有效信息就越多)
// 1、计算出均值
// 2、计算每个元素与平均值的差的平方
// 3、计算平方差的平均值,得到的平方差相加,然后除以数据点的总数
// 4、取平方根:将平均平方差的值进行平方根运算,得到标准方差。
void test10()
{namedWindow("new",WINDOW_AUTOSIZE);Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/green.jpg",cv::IMREAD_GRAYSCALE);double minv,maxv;Point minLoc,maxLoc;minMaxLoc(src,&minv,&maxv,&minLoc,&maxLoc,Mat());cout<<"minv:"<<minv<<" maxv:"<<maxv<<" minLoc:"<<minLoc<<" maxLoc:"<<maxLoc<<endl;Mat mean,stddev;meanStdDev(src,mean,stddev);cout<<mean<<" "<<stddev<<endl;
}
9、绘制图像
void test11()
{namedWindow("new",WINDOW_AUTOSIZE);Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/green.jpg",cv::IMREAD_COLOR);// 绘制矩形Mat bg = Mat::zeros(src.size(),src.type());Mat dst;Rect rect(100,100,200,200);rectangle(bg,rect,Scalar(20,20,255),2,LINE_8,0);// 绘制圆,圆心坐标Point,15是半径circle(src,Point(350,400),150,Scalar(255,0,0),2,LINE_8,0);// 图像融合addWeighted(src,0.7,bg,0.3,0,dst);// 绘制线 两个点的位置line(bg,Point(100,100),Point(350,400),Scalar(0,255,0),2,LINE_8,0);// 绘制椭圆RotatedRect rrt;rrt.center = Point(200,200);rrt.size = Size(100,200);rrt.angle = 0;ellipse(src,rrt,Scalar(0,255,255),2,8);imshow("new",dst);waitKey(0);
}
10、多边形绘制
// 多边形绘制
void test13()
{Mat bg = Mat::zeros(Size(512,512),CV_8UC3);Point p1(100,200);Point p2(350,100);Point p3(450,280);Point p4(320,450);Point p5(80,400);vector<Point> pts;pts.push_back(p1);pts.push_back(p2);pts.push_back(p3);pts.push_back(p4);pts.push_back(p5);polylines(bg,pts, true,Scalar(0,0,255),2,LINE_8,0);// 填充多边形
// fillPoly()imshow("new",bg);waitKey(0);
}
11、随机数
void test12()
{Mat bg = Mat::zeros(Size(512,512),CV_8UC3);int w = bg.cols;int h = bg.rows;// 随机数RNG rng(12345);while (true){int c = waitKey(10);if(c == 27) break;int x1 = rng.uniform(0,w);int y1 = rng.uniform(0,h);int x2 = rng.uniform(0,w);int y2 = rng.uniform(0,h);// 每次画之前清理一下bg = Scalar(0,0,0);line(bg,Point(x1,y1),Point(x2,y2),Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),1,LINE_AA,0);imshow("new",bg);}
}
12、鼠标实时绘制矩形
Point sp(-1, -1);
Point ed(-1, -1);
Mat temp;static void on_draw(int event, int x, int y, int flags, void* userdata)
{Mat img = *((Mat*)userdata);if (event == EVENT_LBUTTONDOWN) {sp.x = x;sp.y = y;cout << "sp.x:" << sp.x << " sp.y:" << sp.y << endl;}else if (event == EVENT_LBUTTONUP) {ed.x = x;ed.y = y;cout << "ed.x:" << ed.x << " ed.y:" << ed.y << endl;int x1 = x - sp.x;int y1 = y - sp.y;if (x1 > 0 && y1 > 0) {Rect rect(sp.x, sp.y, x1, y1);temp.copyTo(img);imshow("ROI区域", img(rect));rectangle(img,rect,Scalar(0,0,255),2,8,0);imshow("new", img);sp.x = -1;sp.y = -1;}}else if (event == EVENT_MOUSEMOVE) {if (sp.x > 0 && sp.y > 0) {ed.x = x;ed.y = y;int dx = ed.x - sp.x;int dy = ed.y - sp.y;if (dx > 0 && dy > 0) {Rect box(sp.x, sp.y, dx, dy);temp.copyTo(img);rectangle(img, box, Scalar(0, 0, 255), 2, 8, 0);imshow("new", img);}}}
}void test14()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);setMouseCallback("new", on_draw, (void*)&src);src.copyTo(temp);imshow("new", src);waitKey(0);destroyAllWindows();
}
13、归一化
// 1、MINMAX
void test15()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);Mat img,img2;cout<<src.type()<<endl;src.convertTo(src,CV_32FC3);cout<<src.type()<<endl;normalize(src,img,1.0,0,NORM_MINMAX);// imshow想显示浮点数据,必须归一化0-1之间imshow("new",img);normalize(img,img2,255.0,0,NORM_MINMAX);img2.convertTo(img2,CV_8UC3);imshow("new1",img2);waitKey(0);
}
14、resize操作
// resize
void test16()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);Mat zoomin,zoomout;int w = src.cols;int h = src.rows;resize(src,zoomin,Size(w/2,h/2),0,0,INTER_LINEAR);resize(src,zoomout,Size(w*1.5,h*1.5),0,0,INTER_LINEAR);imshow("1",src);imshow("2",zoomin);imshow("3",zoomout);waitKey(0);
}
15、旋转翻转
void test17()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");
// namedWindow("new", WINDOW_AUTOSIZE);Mat dst,left,m1,m3;flip(src,dst,0);flip(src,left,1);flip(src,m1,-1);imshow("上下翻转",dst);imshow("左右翻转",left);imshow("180度旋转",m1);waitKey(0);// 图像旋转Mat d,M;int w = src.cols;int h = src.rows;M = getRotationMatrix2D(Point2f(w/2,h/2),45,1.0);double cos = abs(M.at<double>(0,0));double sin = abs(M.at<double>(0,1));int nw = cos * w + sin * h;int nh = sin * w + cos * h;M.at<double>(0,2) += (nw/2-w/2);M.at<double>(1,2) += (nh/2-h/2);warpAffine(src,d,M,Size(nw,nh),INTER_LINEAR,0,Scalar(0,0,255));imshow("new",d);waitKey(0);
}
16、视频操作
void test18()
{VideoCapture cap(0);Mat fram;while(true){cap.read(fram);if(fram.empty()){break;}flip(fram,fram,1);imshow("new",fram);int n = waitKey(10);if(n == 27){break;}}cap.release();
}
17、模糊操作
// 图像卷积模糊操作
void test19()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);Mat dst;blur(src,dst,Size(3,3),Point(-1,-1));imshow("new",dst);waitKey(0);
}
18、高斯模糊操作
// 高斯双边模糊
void test21()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);Mat dst;bilateralFilter(src,dst,0,100,10);imshow("new",dst);waitKey(0);
}// 高斯模糊
void test20()
{Mat src = imread("/Users/zhulei/CLionProjects/opencv_test/1.jpg");namedWindow("new", WINDOW_AUTOSIZE);Rect rect(100,100,500,500);Mat roi = src(rect);GaussianBlur(roi,roi,Size(0,0),15);roi.copyTo(src(rect));imshow("new",src);waitKey(0);
}