图像上绘制几何图形
绘制圆形
void cv::circle ( InputOutputArray img,
Point center, // 圆心
int radius, // 半径
const Scalar & color,
int thickness = 1, // 边界宽度 负数实心
int lineType = LINE_8, // 边界类型
int shift = 0 // 中心坐标和半径数值的小数位数
)
void cv::line ( InputOutputArray img,
Point pt1, // 起点
Point pt2, // 终点
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 // 点坐标中的小数位数。
)
void cv::ellipse ( InputOutputArray img,
Point center, // 椭圆中心
Size axes, // 主轴的一半
double angle, // 旋转角度
double startAngle, // 椭圆弧的起始角度,度
double endAngle, // 终止角度
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
// 输出椭圆边界的像素坐标,不会绘制椭圆
void cv::ellipse2Poly ( Point center,
Size axes,
int angle,
int arcStart,
int arcEnd,
int delta,
std::vector< Point > & pts //存储椭圆边缘的坐标点
)
// 绘制矩形
void cv::rectangle ( InputOutputArray img,
Point pt1, // 对角点
Point pt2,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
void cv::rectangle ( InputOutputArray img,
Rect rec, // 左上顶点坐标和长宽
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0
)
Rect变量与Point一样表示矩形的含义,表示的时矩形的左上角坐标和 w,h。Rect2i,Rect2d,Rect2f
// 多边形
void cv::fillPoly ( InputOutputArray img,
const Point ** pts, // 多边形顶点数组,可以存放多个多边形的顶点坐标的数组
const int * npts, // 每个多边形顶点数组中顶点的个数,数组
int ncontours, // 多边形的个数
const Scalar & color,
int lineType = LINE_8,
int shift = 0,
Point offset = Point()
)
void cv::putText ( InputOutputArray img,
const String & text,
Point org, // 左上角坐标
int fontFace, // 字体
double fontScale, // 字体大小
Scalar color,
int thickness = 1,
int lineType = LINE_8,
bool bottomLeftOrigin = false // 图像原点位置,默认左上,true改为左下
)
using namespace std;
using namespace cv;
int main()
{
Mat img = Mat::zeros(Size(512, 512), CV_8UC3); // 底图
circle(img, Point(50, 50), 25, Scalar(255, 255, 255), -1);
circle(img, Point(50, 50), 50, Scalar(124, 22, 79), 4);
line(img, Point(100, 100), Point(200, 200), Scalar(33, 33, 33), 2, LINE_4, 0);
ellipse(img, Point(300, 255), Size(100, 70), 0, 0, 100, Scalar(44, 44, 44), -1); // 逆时针
ellipse(img, RotatedRect(Point2f(150, 100), Size2f(30, 20), 0), Scalar(0, 0, 255), 2);
vector<Point> points;
ellipse2Poly(Point(200, 400), Size(100, 70), 0, 0, 360, 2, points); // 近似个椭圆
for (int i = 0; i < points.size() - 1; i++)
{
if (i == points.size() - 1)
{
line(img, points[0], points[1], Scalar(255, 255, 255), 2);
}
}
rectangle(img, Point(50, 400), Point(100, 400), Scalar(125, 125, 125), -1);
rectangle(img, Rect(400, 450, 60, 50), Scalar(0, 125, 125), 2);
// 多边形
Point pp[2][6];
pp[0][0] = Point(72, 200);
pp[0][1] = Point(142, 204);
pp[0][2] = Point(226, 263);
pp[0][3] = Point(172, 310);
pp[0][4] = Point(117, 319);
pp[0][5] = Point(15, 260);
pp[1][0] = Point(359, 339);
pp[1][1] = Point(447, 351);
pp[1][2] = Point(504, 349);
pp[1][3] = Point(484, 433);
pp[1][4] = Point(418, 449);
pp[1][5] = Point(354, 402);
Point pp2[5];
pp2[0] = Point(350, 83);
pp2[1] = Point(463, 90);
pp2[2] = Point(500, 171);
pp2[3] = Point(421, 194);
pp2[4] = Point(338, 141);
const Point* pts[3] = { pp[0],pp[1],pp2 }; //pts变量的生成
int npts[] = { 6,6,5 };
fillPoly(img, pts, npts, 3, Scalar(125, 125, 125), 8);
putText(img, "HHH", Point(100, 400), 2, 1, Scalar(255, 122, 144));
imshow("", img);
waitKey(0);
return 0;
}
感兴趣区域
从原图中截取部分进行处理(ROI),可以使用Rect 进行标记位置,或Range标记。另外,对于图像的赋值和拷贝分为浅拷贝,深拷贝。浅拷贝就是建立一个能访问数据的变量,不能独立。= 赋值就是浅拷贝,慎用。深拷贝就是创建变量的同时分配新的地址用于存储数据。copyTo()实现深拷贝
void cv::Mat::copyTo ( OutputArray m ) const
void cv::Mat::copyTo ( OutputArray m,
InputArray mask
) const
当掩模矩阵中某一位置不为 0时,表示复制原图像中相同位置的元素到新的图像中否则便不复制.
void cv::copyTo ( InputArray src,
OutputArray dst,
InputArray mask
)
Mat img = imread("lena.png");
Mat noobcv = imread("noobcv.jpg");
Mat ROI1, ROI2, ROI2_copy, mask, img2, img_copy, img_copy2;
resize(noobcv, mask, Size(200, 200));
img2 = img;
img.copyTo(img_copy2);
copyTo(img, img_copy, img);
Rect rect(206, 206, 200, 200);
ROI1 = img(rect);
ROI2 = img(Range(300, 500), Range(300, 500));
img(Range(300, 500), Range(300, 500)).copyTo(ROI2_copy);
mask.copyTo(ROI1);
imshow("加入noobcv后图像", img);
imshow("ROI对ROI2的影响", ROI2);
imshow("深拷贝的ROI2_copy", ROI2_copy);
circle(img, Point(300, 300), 20, Scalar(0, 0, 255), -1);
imshow("浅拷贝的img2", img2);
imshow("深拷贝的img_copy", img_copy);
imshow("深拷贝的img_copy2", img_copy2);
imshow("画圆对ROI1的影响", ROI1);
图像金字塔
通过多个分辨率表示图像的一种有效简单的结构,金字塔就是分辨率逐渐降低的图像的集合。
- 高斯金字塔
构建金字塔是解决不确定性的一种常用方式,高斯金字塔就是通过下采样不断减小尺寸。尺寸缩小一半。该函数首先将原始图像与内核矩阵进行卷积,然后通过剔除偶数行和列来下采样,实现的功能与 resize() 一样,就是使用的内部算法不同。。
void cv::pyrDown ( InputArray src,
OutputArray dst,
const Size & dstsize = Size(),
int borderType = BORDER_DEFAULT
)
- 拉普拉斯金字塔,高斯通过底层图像向上构建图像,拉普拉斯通过上层小尺寸图像向下构建大尺寸图像。具有预测残差的作用,需要和高斯金字塔联合使用。
假设一个高斯金字塔,对其中某层图像首先通过下采样得到缩小一半的图像,然后对这幅图像进行上采样,恢复尺寸,再求高斯金字塔的该层和上采样后的差值图,这个差值图就是拉普拉斯金字塔的一层。 pyrUp() 参数同上
int main()
{
Mat img = imread("lena.png");
vector<Mat> Gauss, Lap;
int level = 3;
Gauss.push_back(img);
for (int i = 0; i < level; i++)
{
Mat gauss;
pyrDown(Gauss[i], gauss);
Gauss.push_back(gauss);
}
for (int i = Gauss.size() - 1; i > 0; i--)
{
Mat lap, upGauss;
if (i == Gauss.size() - 1)
{
Mat down;
pyrDown(Gauss[i], down);
pyrUp(down, upGauss);
lap = Gauss[i] - upGauss;
Lap.push_back(lap);
}
pyrUp(Gauss[i], upGauss);
lap = Gauss[i - 1] - upGauss;
Lap.push_back(lap);
}
for (int i = 0; i < Gauss.size(); i++)
{
string name = to_string(i);
imshow("G" + name, Gauss[i]);
imshow("L" + name, Lap[i]);
}
waitKey(0);
return 0;
}
窗口交互操作
用于对流程的控制,比如修改一些参数啥的。
滑动条
动态调整某些数值。
int cv::createTrackbar ( const String & trackbarname,
const String & winname,
int * value,
int count,
TrackbarCallback onChange = 0,
void * userdata = 0
)
该函数可以在窗口上方创建一个从0开始的整数滑动条,只能输出整数,小数就需要后续处理。第五个参数是每次滑块更改位置时调用的函数的指针,最后一个参数时传递给回掉函数的 void* 数据
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int value;
void callBack(int, void*);
Mat img1, img2;
int main()
{
img1 = imread("lena.png");
namedWindow("滑动条");
imshow("滑动条", img1);
value = 100;
createTrackbar("亮度百分比", "滑动条", &value, 600, callBack, 0);
waitKey();
}
static void callBack(int, void *)
{
float a = value / 100.0;
img2 = img1 * a;
imshow("滑动条", img2);
cout << value << endl;
}
鼠标响应
void cv::setMouseCallback ( const String & winname,
MouseCallback onMouse,
void * userdata = 0
)
typedef void(* cv::MouseCallback) (int event, int x, int y, int flags, void *userdata)
响应事件,鼠标指针在图像的x,y坐标,响应标志,函数名可以任意设置。在鼠标状态改变时调用
在鼠标位于图像窗口内时,时刻检测鼠标状态,发生改变时调用回调函数,根据回调函数中的判断逻辑执行响应的操作。比如,回调函数只处理左键按下事件,即判断event标志是否为 EVENT_LBUTTONDOWN, 当左键按下,执行对应的逻辑操作。
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Mat img, imgPoint;
Point prePoint;
void mouse(int event, int x, int y, int flags, void *);
int main()
{
img = imread("lena.png");
img.copyTo(imgPoint);
imshow("1", img);
namedWindow("2", 0);
imshow("2", imgPoint);
setMouseCallback("1", mouse, 0);
waitKey(0);
return 0;
}
void mouse(int event, int x, int y, int flags, void *)
{
if (event == EVENT_RBUTTONDOWN)
{
cout << "nonono";
}
if (event == EVENT_LBUTTONDOWN)
{
prePoint = Point(x, y);
cout << "起始坐标" << prePoint << endl;
}
if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
imgPoint.at<Vec3b>(y, x) = Vec3b(0, 0, 255);
imgPoint.at<Vec3b>(y, x - 1) = Vec3b(0, 0, 255);
imgPoint.at<Vec3b>(y, x + 1) = Vec3b(0, 0, 255);
imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);
imshow("2", imgPoint);
Point pt(x, y);
line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);
prePoint = pt;
imshow("1", img);
}
}
小结
函数 | 说明 |
---|
circle\line\ellipse\ellipse2Poly\rectangle\fillPoly\putText | 画画 | copyTo | 深拷贝 | pyrDown/pyrUp | 下采样,上采样 | createTrackbar | 创建滑动条 | setMouseCallback | 鼠标响应 |
|