图像 色彩空间转换
图像 创建赋值
//克隆(创建另外一个Mat)
Mat m1 = src.clone();
//复制
Mat m2;
src.copyTo(m2);
//赋值:
Mat m3;
m3 = imread();
m3 = src;
//赋值:创建空白图像
Mat m4 = Mat::zeros(src.size, src.type());
Mat m5 = Mat::zeros(Size(512, 512),CV_8UC3);
Mat m6 = Mat::ones(Size(512, 512), CV_8UC3);
//赋值:C++11新增
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,
-1,5,-1,
0,-1,0);
//赋值:通道赋值
Mat m3 = Mat::zeros(Size(512,512), CV_8UC3);
m3 = Scalar(127,127, 127);
//浅拷贝,m4和m3指向同一个对象
Mat m4 = m3;
图像 像素的读写操作
//eg1:颜色取反
// Mat image;已赋值的Mat
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for(int row = 0;row < h;row++){
for(int col = 0;col < w;col++){
if(dims == 1){//灰度图像
//获取该行列的像素值
int pv = image.at<uchar>(row,col);
image.at<uchar>(row,col) = 255 - pv;
}
if(dims == 3){//彩色图像
//获取该行列的所有通道的像素值
Vec3b bgr = image.at<Vec3b>(row,col);
image.at<Vec3b>(row,col)[0] = 255 - bgr[0];
image.at<Vec3b>(row,col)[1] = 255 - bgr[1];
image.at<Vec3b>(row,col)[2] = 255 - bgr[2];
}
}
}
//eg2:颜色取反
// Mat image;已赋值的Mat
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for(int row = 0;row < h;row++){
//获取该行的首个元素的像素指针
uchar * current_row = image.ptr<uchar>(row);
for(int col = 0;col < w;col++){
if(dims == 1){//灰度图像
int pv = *current_row;
*current_row++; = 255 - pv;
}
if(dims == 3){//彩色图像
*current_row++; = 255 - *current_row*;
*current_row++; = 255 - *current_row*;
*current_row++; = 255 - *current_row*;
}
}
}
图像 像素的算术操作
//eg1:减法操作
//Mat image
Mat dst = image - Scalar(50,50,50);
imshow("减法操作", dst);
//eg2:除法操作
//Mat image
Mat dst = image/Scalar(2,2,2);
imshow("除法操作", dst);
//eg3:乘法操作
//Mat image
Mat m = Mat::zeros(image.size, image.type());
m = Scalar(2, 2, 2);
multiply(image, m , dst);
imshow("乘法操作", dst);
//eg4:加法扩展
//Mat image
Mas dst = Mat::zeros(image.size, image.type());
Mas m = Mat::zeros(image.size, image.type());
m = Scalar(50,50,50);
//加法
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for(int row = 0;row < h;row++){
for(int col = 0;col < w;col++){
if(dims == 1){//灰度图像
//获取该行列的像素值
// int pv = image.at<uchar>(row,col);
// image.at<uchar>(row,col) = 255 - pv;
}
if(dims == 3){//彩色图像
//获取该行列的所有通道的像素值
Vec3b p1 = image.at<Vec3b>(row,col);
Vec3b p2 = m.at<Vec3b>(row,col);
dst.at<Vec3b>(row,col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
dst.at<Vec3b>(row,col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
dst.at<Vec3b>(row,col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
}
}
}
//eg5:api
Mas dst = Mat::zeros(image.size, image.type());
Mas m = Mat::zeros(image.size, image.type());
m = Scalar(50,50,50);
add(image, m, dst);//加法
// subtract(image, m, dst);//减法
// divide(image, m, dst);//除法
imshow("运算操作", dst);
滚动条操作演示 调整图像亮度
//回调函数,亮度回调值
static void on_track(int,void*){
Mas dst = Mat::zeros(image.size, image.type());
Mas m = Mat::zeros(image.size, image.type());
}
namedWindow("亮度调整", WINDOW_AUTOSIZE);
int max_value = 100;
int lightness = 50;
createTrackbar("Value", "亮度调整", &lightness, max_value, on_track);
on_track(50,0);//设置一个默认值
滚动条操作演示-参数传递度
//回调函数,亮度回调值
static void onLightness(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWerghted(image,1.0,m,0,b,dst);
imshow("亮度与对比度调整",dst);
}
//回调函数,亮度与对比度调整
static void onContrast(int b, void* userdata) {
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
doublt contrast = b / 100.0;
addWerghted(image,contrast,m,0.0,0,dst);
imshow("亮度与对比度调整",dst);
}
void tracking_bar_demo(Mat &image){
namedWindow("亮度调整", WINDOW_AUTOSIZE);
int max_value = 100;
int lightness = 50;
int contrast_value = 100;
createTrackbar("Value", "亮度与对比度调整", &lightness, max_value, onLightness,(void*)(&image));
createTrackbar("Contrast Bar", "亮度与对比度调整", &contrast_value, max_value200, onContrast,(void*)(&image));
on_lightness(50,&image);
}
键盘响应操作 waitKey
void key_demo(Mat &image){
Mat dst;
//监听键盘操作
while(true){
char c = waitKey(10);
std::cout << c << std::endl;
}
}
openCV自带颜色表操作 applyColorMap
void colorStyleDemo(Mat &image){
int colormap[]= {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA,
COLORMAP_MAGMA,
COLORMAP_INFERNO,
COLORMAP_PLASMA,
COLORMAP_VIRIDIS,
COLORMAP_CIVIDIS,
COLORMAP_TWILIGHT,
COLORMAP_TWILIGHT_SHIFTED
};
Mat dst;
int index = 0;
while(true){
int c = waitKey(2000);
if(c == 27){//退出
break;
}
applyColorMap(image, dst, colormap[index%19]);
index++;
imshow("颜色风格", dst);
}
}
rectangle 图像像素的逻辑操作
void bitWiseDemo(Mat &image){
Mat m1 = Mat::zero(Size(256,256),CV_8UC3);
Mat m2 = Mat::zero(Size(256,256),CV_8UC3);
rectangle(m1,//图像对象
Rect(100,100,80,80),//位置
Scalar(255,255,0),//bgr
-1, //-1:绘制、2:描边
LINE_8,
0);
rectangle(m2,Rect(150,150,80,80),Scalar(0,255,255),-1,LINE_8,0);
imshow("m1",m1);
imshow("m2",m2);
Mat dst;
bitwise_and(m1,m2,dst);
//bitwise_or(m1,m2,dst);//或
//bitwise_nor(m1,m2,dst);//非
//dst = ~image;//非
imshow("像素位操作",dst);
}
通道分离和合并
void channels_demo(Mat &image){
//通道分离
std::vector<Mat> mv;
split(image,mv);
imshow("蓝色",mv[0]);
imshow("绿色",mv[1]);
imshow("红色",mv[2]);
//通道合并
Mat dst;
mv[1] = 0;
mv[2] = 0;
merge(mv,dst);
imshow("蓝色",dst);
int from_to[] = {0,2,//0通道换到2通道
1,1,
2,0};
mixChannels(&image,1,&dst,1,
from_to,
3);//3对交换的通道
imshow("通道混合",dst);
}
图像色彩空间转换
void inrange_demo(Mat &image){
Mat hsv;
//转换色彩空间
cvtColor(image,hsv,COLOR_BGR2HSV);
//提取
Mat mask;
inRange(hsv,Scalar(35,43,46),Scalar(77,255,255),mask);
//eg1:显示
Mat redback = Mat::zeros(image.size(),image.type());
redback = Scalar(40,40,200);
//取反
bitwise_not(mask,mask);
//eg2:显示
imshow("mask",mask);
image.copyTo(redback,mask);
//eg3:roi区域提取
}
图像像素值统计
void pixel_statistic_demo(Mat &iamge){
int minv,max;
Point minLoc,maxLoc;
std::vector<Mat> mv;
//通道分离
split(image,mv);
for (int i = 0; i < mv.size(); ++i) {
minMaxLoc(mv[i],&minv,&maxv,&minLoc,&maxLoc,Mat());
std::cout << "No. channels:"
<< i << "min value" << minv
<< "max value:" << maxv << std::endl;
}
Mat mean,stddev;
Mat redback = Mat::zeros(image.size().image.type());
meanStdDev(redback,mean,stddev);
imshow("redback",redback);
std::cout << "means:" << mean << std::endl;
std::cout << "stddev:" << stddev << std::endl;
}
算出的方差
判断图像对比度差异大小(方差、对比度成正比)
图像几何形状绘制
//图像几何形状绘制
void drawing_demo(Mat &image){
Rect rect;
rect.x = 100;
rect.y = 100;
rect.width = 250;
rect.height = 300;
Mat bg = Mat::zeros(image.size(), image.type());
//绘制矩形
rectangle(bg, rect, Scalar(0, 0, 255), -1, 8, 0);
//绘制圆
circle(bg, Point(350, 400), 15, Scalar(255, 0, 0), -1, 8, 0);
//绘制线
line(bg, Point(100, 100), Point(350, 400), Scalar(0, 255, 0), 4, LINE_AA, 0);
//绘制椭圆
RotatedRect rrt;
rrt.center = Point(200, 200);
rrt.size = Size(100, 200);
rrt.angle = 90.0;
ellipse(bg, rrt, Scalar(0, 255, 255), 2, 8);
//图像合并
Mat dst;
addWeighted(image, 0.7, bg, 0.3, 0, dst);
imshow("绘制演示", bg);
}
随机数与随机颜色
//eg1:随机数与随机颜色
void random_drawing(Mat &image){
Mat canvas = Mat::zeros(Size(512,512),image.type());
int w = canvas.cols;
int h = canvas.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);
int b = rng.uniform(0,255);
int g = rng.uniform(0,255);
int r = rng.uniform(0,255);
//绘制线
line(bg, Point(100, 100), Point(350, 400), Scalar(b, g, r),
1, LINE_AA, 0);
ishow("随机绘制演示",canvas);
}
多边填充与绘制
//多边形填充与绘制
void polyline_drawing_demo(){
Mat canvas = Mat::zeros(Size(512,512),CV_8UC3);
Point p1(100,100);
Point p1()100,100;Point p2(350, 100);
Point p3(450, 280);
Point p4(320, 450);
Point p5(80, 400);
std::vector<Point> pts;
pts.push back(p1);
pts.push back(p2);
pts.push back(p3);
pts.push back(p4);
pts.push back(p5);
//fillPoly(canvas, pts, Scalar(255, 0, 255), 8, 0);
//polylines(canvas, pts, true, Scalar(0, 0, 255), 2, LINE AA, 0);
std::vector<std::vector<Point>> contours;
contours.push back(pts);
drawContours(canvas, contours, -1, Scalar(255, 0, 0), -1);
imshow("多边形绘制"canvas);
}
鼠标操作与响应
//eg1
Point sp;
Point ep;
Mat temp;
static void on_draws(int event,int x,int y,int flags,void *userdata){
Mat image = *((Mat*)userdata);
switch(event){
case EVENT_LBUTTONDOWN:
{
sp.x = x;
sp.y = y;
std::cout << "start point:" << sp << endl;
}
break;
case EVENT_LBUTTONUP:
{
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if(dx - 0 && dy > 0){
Rect box(sp.x,sp.y,dx,dy);
imshow("roi区域",image(box));
rectangle(image, box, Scalar(0,0,255),2,8,0);
imshow("鼠标绘制",image);
sp.x = -1;
sp.y = -1;
}
}
break;
case EVENT_MOUSEMOVE:
{
if(sp.x - 0 && sp.y > 0){
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if(dx - 0 && dy > 0){
Rect box(sp.x,sp.y,dx,dy);
temp.copyTo(image);
rectangle(image, box, Scalar(0,0,255),2,8,0);
imshow("鼠标绘制",image);
}
}
}
break;
default:
break;
}
}
//鼠标操作与响应
void mouse_drawing_demo(Mat &image){
namedWindow("鼠标绘制",WINDOW_AUTOSIZE);
//设置鼠标事件回调函数
setMouseCallback("鼠标绘制",on_draws,(void*)&image);
imshow("鼠标绘制",image);
temp = image.clone();
}
图像像素类型转换与归一化
//图像数据归一化
void norm_demo(Mat &image){
Mat dst;
std::cout << image.type() << endl;
//图像像素类型转换
image.convertTo(image, CV_32F);
std::cout << image.type() << endl;
//图像数据归一化
normalize(image, dst, 1.0, 0, NORM_MINMAX);
cout << dst.type() << endl;
imshow("图像数据归一化", dst);
}
图像放缩与插值
//图像的放缩与插值
void resize_demo(Mat &image){
Mat zoomin,zoomout;
int h = image.rows;
int w = image.clos;
//缩小
resize(image,zoomout,Size(w/2,h/2),0,0,INTER_LINEAR);
imshow("zoomout",zoomout);
//放大
resize(image,zoomin,Size(w*1.5,h*1.5),0,0,INTER_LINEAR);
imshow("zoomin", zoomin);
}
图像旋转
eg1:flip
//图像旋转
void flip_demo(Mat &image){
Mat dst;
//flip(image,dst,0);//上下旋转
//flip(image,dst,1);//左右旋转
flip(image,dst,-1);//180°旋转
imshow("图像旋转",dst);
}
eg2:warpAffine
void rotate_demo(Mat &image){
Mat dst,M;
int w = image.cols;
int h = image.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 = cow*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(image,dst,M,Size(nw,nh),INTER_LINEAR,0,Scalar(255,255,0));
imshow("旋转演示",dst);
}
视频文件摄像头使用
//视频文件摄像头使用
void video_demo(){
//打开摄像头:默认摄像头
VideoCapture capture(0);
Mat frame;
while(true){
//读码摄像头数据
capture.read(frame);
//旋转Mat图像:1左右旋转
flip(frame,frame,1);
if(frame.empty()){
break;
}
imshow("frame",frame);
//TODO:do something...
//获取键盘事件
int c = waitKey(1);
if(c == 27){//退出
break;
}
}
//关闭摄像头
capture.release();
}
视频处理与保存
//视频文件摄像头使用
void video_demo(){
//打开摄像头:默认摄像头
VideoCapture capture(0);
//摄像头的视频属性
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
int frame_count = capture.get(CAP_PROP_FRAME_COUNT);
double fps = capture.get(CAP_PROP_FPS);
cout << "frame_width:" << frame_width << endl;
cout << "frame_height:" << frame_height << endl;
cout << "frame_count:" << frame_count << endl;
cout << "fps:" << fps << endl;
//打开VideoWrite
VideoWrite writer("D:/test.mp4",
cpature.get(CAP_PROP_FOURCC),
fps,
Size(frame_width,frame_height),
true);
Mat frame;
while(true){
//读码摄像头数据
capture.read(frame);
//旋转Mat图像:1左右旋转
flip(frame,frame,1);
if(frame.empty()){
break;
}
imshow("frame",frame);
writer.write(frame);
//TODO:do something...
//获取键盘事件
int c = waitKey(1);
if(c == 27){//退出
break;
}
}
//关闭摄像头
capture.release();
//关闭视频保存对象
writer.release();
}
图像直方图
void showHistogram(cv::Mat &src)
{//通道分离
vector<Mat> bgr_plane;
split(src,bgr_plane) ;// 定义参数恋量
const int channels[1] = {0};
int bins[1] = { 256};
float hranges[2] = {0,255};
const float* ranges[1] = { hranges };
Mat b_hist;
Mat g_hist;
Mat r_hist;// 计算Blue,Green,Red通道的直方图
calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins,ranges);
calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins,ranges);
calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
//显示直方图
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros (hist_h, hist_w, CV_8UC3);
// 归一化直方图数据
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
// 绘制直方图曲线
for (int i = 1;i < bins[0]; i++) {
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
}
// 显示直方图
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}
) {
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at(i))), Scalar(255, 0, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at(i - 1))),
Point(bin_w*(i), hist_h - cvRound(g_hist.at(i))), Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at(i - 1))),
Point(bin_w*(i), hist_h - cvRound(r_hist.at(i))), Scalar(0, 0, 255), 2, 8, 0);
}
// 显示直方图
namedWindow(“Histogram Demo”, WINDOW_AUTOSIZE);
imshow(“Histogram Demo”, histImage);
}