#include
#include
#define MATCHMETHOD TM_SQDIFF_NORMED//宏定义匹配模式
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("./image/test10.jpg");
Mat src_gray, binary;
Mat Triangle = src.clone(), Rect = src.clone(), BigCircle = src.clone(), SmallCircle = src.clone();
if (src.empty()) {
printf("Could not load image...");
return -1;
}
imshow("Input Image", src);
//二值化
cvtColor(src, src_gray, COLOR_BGR2GRAY);
threshold(src_gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
binary = ~binary;
imshow("binary", binary);
//发现轮廓
vector<vector<Point>> contours;
vector<Point> point;
vector<Vec4i> hireachy;
findContours(binary, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
//绘制出所有轮廓
for (size_t t = 0; t < contours.size(); t++)
{
int epsilon = 0.01 * arcLength(contours[t], true);
approxPolyDP(contours[t], point, epsilon, true);
if (point.size() == 3)
{
drawContours(Triangle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else if (point.size() == 4)
{
drawContours(Rect, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else
{
double area = contourArea(contours[t]);
if (area < 15000)
{
drawContours(SmallCircle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else
{
drawContours(BigCircle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
}
cout << "边的数目:" << point.size() << endl;
}
imshow("Triangle", Triangle);
imshow("BigCircle", BigCircle);
imshow("Rect", Rect);
imshow("SmallCircle", SmallCircle);
waitKey(0);
return 0;
}
对指定的点集进行多边形逼近的函数,其逼近的精度可通过参数设置。
void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);
说明:该函数用于绘制图像中的轮廓(若thickness >= 0)或者填充轮廓所包围的区域(若thickness < 0)
CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
注:
当thickness = FILLED,即使没有提供层级信息也可以正确处理带孔洞的连通域情况(分析轮廓时采用奇偶规则),但如果是单独检索的轮廓合并则可能会出现错误的情况,该情况下则需要分开处理。
double contourArea(InputArray contour, bool oriented = false);
寻找轮廓时,取的点为像素中心点,连接起来的黑线就是这个图形的轮廓,那么计算的周长应该是4个对角+4个三角(42+42*≈19.313708499),与计算机输出的结果一致。
double arcLength(InputArray curve, bool closed);
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat A = Mat::zeros(300, 350, CV_8UC1);
rectangle(A, Point(10, 100), Point(50, 140), Scalar(255, 0, 0));//画矩形 draw rectangle
circle(A, Point2i(100, 100), 3, 255, -1);
circle(A, Point2i(250, 100), 50, 255, -1);
//寻找轮廓
vector<vector<Point> >contours;
findContours(A, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
//计算并输出面积周长
Mat dst = Mat::zeros(A.size(), A.type());
RNG rngs = { 12345 };
for (int i = 0; i < contours.size(); i++)
{
Scalar colors = Scalar(rngs.uniform(0, 255), rngs.uniform(0, 255), rngs.uniform(0, 255));
drawContours(dst, contours, i, colors, 1);
cout << i << " 的面积:" << contourArea(contours[i]) << endl;
cout << " 周长:" << arcLength(contours[i], true) << endl;
}
imshow("A", A);
waitKey(0);
}
#include
#include
#define MATCHMETHOD TM_SQDIFF_NORMED//宏定义匹配模式
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("../data/test6.jpg");
Mat src_gray, binary;
Mat Triangle = src.clone(), Rect = src.clone(), BigCircle = src.clone(), SmallCircle = src.clone();
if (src.empty()) {
printf("Could not load image...");
return -1;
}
imshow("Input Image", src);
//二值化
cvtColor(src, src_gray, COLOR_BGR2GRAY);
threshold(src_gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
binary = ~binary;
imshow("binary", binary);
//发现轮廓
vector<vector<Point>> contours;
vector<Point> point;
vector<Vec4i> hireachy;
findContours(binary, contours, hireachy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
//绘制出所有轮廓
for (size_t t = 0; t < contours.size(); t++)
{
int epsilon = 0.01 * arcLength(contours[t], true);
approxPolyDP(contours[t], point, epsilon, true);
if (point.size() == 3)
{
drawContours(Triangle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else if (point.size() == 4)
{
drawContours(Rect, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else
{
double area = contourArea(contours[t]);
if (area < 15000)
{
drawContours(SmallCircle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
else
{
drawContours(BigCircle, contours, t, Scalar(0, 0, 255), 2, 8, Mat(), 0, Point());//dst必须先初始化
}
}
cout << "边的数目:" << point.size() << endl;
}
imshow("Triangle", Triangle);
imshow("BigCircle", BigCircle);
imshow("Rect", Rect);
imshow("SmallCircle", SmallCircle);
waitKey(0);
return 0;
}
在图像处理的领域,我们常常需要去设置自己感兴趣的区域(ROI,region of interest),来专注或者简化工作过程。也就是从图像中选择的一个图像区域,这个区域是图像分析所关注的重点。我们圈定这个区域,以便进行下一步的处理。而且,使用ROI指定想读入的目标,可以减少处理时间,增加精度,给图像处理带来不小的便利。
void cvInRange( const CvArr* src, const CvArr* lower, const CvArr* upper,CvArr* dst )
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("E:../data/test8.jpg");
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
int h = src.rows;
int w = src.cols;
//get ROI
int cy = h / 2;
int cx = w / 2;
Rect rect(cx - 100, cy - 100, 200, 200);
Mat roi = src(rect);
imshow("roi", roi);
Mat image = roi.clone();
// modify ROI
roi.setTo(Scalar(255, 0, 0));
imshow("result", src);
//modif copy roi
image.setTo(Scalar(255, 0, 0));
imshow("result", src);
imshow("copy roi", image);
//example with ROI - generate mask
Mat src2 = imread("E:../data/test3.jpg");
imshow("src2", src2);
Mat hsv, mask;
cvtColor(src2, hsv, COLOR_BGR2HSV);
//That is, dst (I) is set to 255 (all 1 -bits) if src (I) is within the
//specified 1D, 2D, 3D, ... box and 0 otherwise.
inRange(hsv, Scalar(100, 43, 46), Scalar(124, 255, 255), mask);//within the wise set to 255,if not,set 0
imshow("mask", mask);//get the mask exclusive person
//extract person ROI
Mat person;
bitwise_not(mask, mask);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(mask, mask, MORPH_CLOSE, kernel);
bitwise_and(src2, src2, person, mask);
imshow("person", person);
//generate background
Mat result = Mat::zeros(src2.size(), src2.type());
result.setTo(Scalar(0, 0, 255));
//combine background + person
Mat dst;
bitwise_not(mask, mask);
bitwise_or(person, result, dst, mask);
add(dst, person, dst);
imshow("dst", dst);
waitKey(0);
return 0;
}
原文链接:https://kings.blog.csdn.net/article/details/83857914
Rect(int x, int y, int width, int height);
参数含义: Rect(左上角x坐标 , 左上角y坐标,矩形的宽,矩形的高)
例如我们画一个图 Rect(20,50,30,40), 我用matlab画了一下,比较直观
那对于Rect(20,50,30,40)有哪些常用的操作?
rect.area(); //返回面积,1200
rect.size();//返回尺寸,30x40
rect.tl();// 返回左上角坐标(20,50)
rect.br();//返回右下角坐标(50,10)
rect.width();//返回宽度30
rect.height();//返回高度40
rect.contains(Point(x,y)) ; //返回布尔true/false, 判断x,y是否在这个矩形中
交集、并集, 矩阵对比,很像C语言
rect = rect1 & rect2;
rect = rect1 | rect2;
rect1 == rect2; //返回布尔值
rect1 != rect2 ; //返回布尔值
Rectangle用法
void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src = imread("../data/image2.png");
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
char file_img[100];
float x = 5, y=25, w=37, h=80 ;
String num[11] = { " ","1","2","3","4","5","6","7","8","9","0"};
for (int i = 1; i <= 10; i++)
{
Rect rect(x, y, w, h);
x += 38.5;
Mat roi = src(rect);
imshow(num[i], roi);
sprintf_s(file_img, "../data/number/%s.jpg",num[i]);// 给file_img赋值:1.jpg 2.jpg等
imwrite(file_img, roi);
}
waitKey(0);
return 0;
}
原文链接:https://www.cnblogs.com/Vince-Wu/p/11855101.html
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
将图像的每个像素用邻域 (以当前像素为中心的正方形区域)像素的 中值 代替 。
void medianBlur( const Mat& src, Mat& dst, int ksize );
将输入数组的每一个像素点与 高斯内核 卷积,将卷积和当作输出像素值。
void GaussianBlur( const Mat& src, Mat& dst, Size ksize,double sigmaX, double sigmaY=0,int borderType=BORDER_DEFAULT );
(cv2 :: fastNlMeansDenoising)使用单个灰度图像
(cv2 :: fastNlMeansDenoisingColored)使用彩色图像。
(cv2 :: fastNlMeansDenoisingMulti)用于在短时间内捕获的图像序列(灰度图像)
(cv2 :: fastNlMeansDenoisingColoredMulti)与上面相同,但用于彩色图像。
fastNlMeansDenoisingColored( InputArray src,
OutputArray dst,
float h = 3, float hColor = 3,
int templateWindowSize = 7, int searchWindowSize = 21)
#include
#include
using namespace cv;
using namespace std;
void add_salt_pepper_noise(Mat& image);
void gaussian_noise(Mat& image);
int main(int artc, char** argv) {
Mat src = imread("E:../data/test6.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
gaussian_noise(src);
Mat result1, result2, result3, result4;
blur(src, result1, Size(5, 5));
imshow("result-1", result1);
GaussianBlur(src, result2, Size(5, 5), 0);
imshow("result-2", result2);
medianBlur(src, result3, 5);
imshow("result-3", result3);
fastNlMeansDenoisingColored(src, result4, 15, 15, 10, 30);
imshow("result-4", result4);
waitKey(0);
return 0;
}
void add_salt_pepper_noise(Mat& image) {
RNG rng(12345);
int h = image.rows;
int w = image.cols;
int nums = 10000;
for (int i = 0; i < nums; i++) {
int x = rng.uniform(0, w);
int y = rng.uniform(0, h);
if (i % 2 == 1) {
image.at<Vec3b>(y, x) = Vec3b(255, 255, 255);
}
else {
image.at<Vec3b>(y, x) = Vec3b(0, 0, 0);
}
}
imshow("salt pepper", image);
}
void gaussian_noise(Mat& image) {
Mat noise = Mat::zeros(image.size(), image.type());
randn(noise, (15, 15, 15), (30, 30, 30));
Mat dst;
add(image, noise, dst);
imshow("gaussian noise", dst);
dst.copyTo(image);
}
高斯双边模糊与mean shift均值模糊两种边缘保留滤波算法,都因为计算量比较大,无法实时实现图像边缘保留滤波,限制了它们的使用场景,OpenCV中还实现了一种快速的边缘保留滤波算法。高斯双边与mean shift均值在计算时候使用五维向量是其计算量大速度慢的根本原因,该算法通过等价变换到低纬维度空间,实现了数据降维与快速计算。
CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1,
float sigma_s = 60, float sigma_r = 0.4f);
#include
#include
using namespace cv;
using namespace std;
int main(int artc, char** argv) {
Mat src = imread("./image/test3.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
Mat dst;
double tt = getTickCount();
edgePreservingFilter(src, dst, 1, 60, 0.44);
double end = (getTickCount() - tt) / getTickFrequency();
printf("time consume : %f\n ", end);
imshow("result", dst);
waitKey(0);
return 0;
}
执行结果:
图像卷积最主要功能有图像模糊、锐化、梯度边缘等,前面已经分享图像卷积模糊的相关知识点,OpenCV除了支持上述的卷积模糊(均值与边缘保留)还支持自定义卷积核,实现自定义的滤波操作。自定义卷积核常见的主要是均值、锐化、梯度等算子。下面的三个自定义卷积核分别可以实现卷积的均值模糊、锐化、梯度功能。
CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT );
#include
#include
using namespace cv;
using namespace std;
int main(int artc, char** argv) {
Mat src = imread("./image/test3.jpg");
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
namedWindow("input", WINDOW_AUTOSIZE);
imshow("input", src);
Mat kernel1 = Mat::ones(5, 5, CV_32F) / (float)(25);
Mat kernel2 = (Mat_<char>(3, 3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
Mat kernel3 = (Mat_<int>(2, 2) << 1, 0, 0, -1);
Mat dst1, dst2, dst3;
filter2D(src, dst1, -1, kernel1);
filter2D(src, dst2, -1, kernel2);
filter2D(src, dst3, CV_32F, kernel3);
convertScaleAbs(dst3, dst3);
imshow("blur=5x5", dst1);
imshow("shape=3x3", dst2);
imshow("gradient=2x2", dst3);
waitKey(0);
return 0;
}