文章目录
- 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截断为255
threshold(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::ImreadModes
CV_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'):
break
cap.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'):
break
else:
break
cap.release()
cv2.release()
cv2.destroyAllWindows()
import cv2
# 色彩空间
# hsv:色相、饱和度、明亮度
# yuv:4:2:0 4:2:2 4:4:4
def callback():
pass
def 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'):
break
cv2.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通道,则只有每个元素的第一个通道为1
Mat m4 = Mat::ones(Size(8,8),CV_8UC3);
cout<<m3.cols<<m3.rows<<m3.channels()<<endl;
// 3通道时候:每个元素的第一个通道为1
m4 = 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);
}