图像加载
Max src = imread(‘adsfaasdf’)
判断图像是否空
src.empyt() = ture or false
src.data
图像框
nameWindow(‘aaa’, CV_WINDOW_AUTOSIZE) 或CV_WINDOW_NORMAL
图像展示
imshow(‘aaa’, src)
修改图像
(改变颜色空间rgb )
cvtColor(src, dst, CV_BGR2GRAY)
保存图像
imwrite(‘image/aaa.jpg’, src)
像素矩阵指针
Mat.ptr(int i=0) ,i表示第几行
获得当前行指针 const uchar* current = my.Image.ptr(row)
像素范围处理
saturate_cast(i)
i < 0 , 返回0;
0 < i < 255, 返回 i;
i > 255 , 返回255;
像素掩模 mask
int rows = src.rows;
int cols=(src.cols-1) * src.channels();一个增加对比度的掩模
[ 0 , -1 , 0;
-1 , 5 , -1;
0 , -1 , 0 ]
图像大小复制
dst = Mat::zeros(src.size(),src.type());
掩模函数
Mat kernel = ( Mat_(3,3) << 0 , -1 , 0 , -1 , 5 , -1 , 0 , -1 , 0 ) ;
filter2D(src , dst , src.depth(), kernel)
src.depth() : 8位,24位,32位 , -1也行
获取执行时间:
double t = getTickCount() ;
Mat 与 IplImage
Mat 是Opecv2.0后引进,不存在内存泄漏的问题
IplImage 是2001年OpenCV发布后一直存在,存在内存泄漏的问题Mat 常用方法
void copyTo( Mat mat)
src.copyTo()void convertTo(mat dst, int type) 类型转换
Max clone()
src.clone()int channels() 通道数
int depth() 位深度
bool empty()
uchar* ptr(i=0)
颜色赋值:
Scalar(double, double, double)
三个double分别代表B G R
Mat对象创建
cv::Mat::Mat
Mat M ( 2, 2, CV_8UC3, Scalar(0,0,255))Mat m1;
m1.create(src.size(), src.type());
m1 = Scalar(0, 0, 255);Mat m2 = Mat::zeros( src.size(), src.type())
Mat m2 = Mat::eye(2 , 2 , 8UC1)
Mat 对象使用
1 部分复制 ( 只复制头,指针 , 不会复制数据部分 )
Mat A = imread ( imgFilePath )
Mat B ( A ) 拷贝构造函数
2 完全复制
Mat F = A.clone()
Mat G; A.copyTo(G);
指针指向对应像素点,并修改对应像素值
int gray = src.at(row, col)
src.at(row, col) = 255 -gray
RGB图像
float b = src.at (row, col ) [0];
float g = src.at (row, col ) [1];
float r = src.at (row, col ) [2];
dst.at (row, col ) [0] = stturate_cast(balpha + beta);
dst.at (row, col ) [1] = stturate_cast(galpha + beta);
dst.at (row, col ) [2] = stturate_cast(r*alpha + beta);
位操作,全部去反
bitwise_not(src, dst);
两图像先行混合函数:
cv::addWeighted( src1, alpha, src2, beta, gamma, dst)
注:确保 类型,大小一致
画点
cv::Point
Point p;
p.x = 10;
p.y = 8;
or
p = Point(10,8);
元素向量
cv::Scalar
Scalar color = Scalar(0, 0, 255); // 红色
Scalar(a, b, c); // a = blue, b = green, c = red 表示RGB三个通道
绘制线,矩形,圆,椭圆等几何形状
线
cv::Line
Point p1 = Point(20,30); //点1
Point p2 = Point(400,400); //点2
Scalar color = Scalar(255, 0, 0); //设置颜色
cv::Line(src, p1, , p2, color , 2 (thickness), LINE_8 (linetype) )
椭圆
cv::ellipse
ellipse(src, Point(src.cols/2,src.rows/2) , Size(src.cols/4,src.rows/8)(长短), 90(倾斜角度) , 0 , 360(0-360画满), color , 2(thickness), LINE_8)
矩形
Rect rect = Rect(x, y, width, height); //画形状
Scalar color = Scalar(255, 0, 0); //设置颜色
cv::rectangle(src, rect, , color, 2 (thickness), LINE_8 (linetype) )
圆
cv::circle
Scalar color = Scalar(255, 0, 0); //设置颜色
Point center = Point(src.cols/2,src.rows/2);//中心
cv::circle(src, center, 150(半径), color, 2, LINE_8)
多边形填充
cv::fillPoly
Point pts[1][5];
pts[0][0] = Point(100,100);
pts[0][1] = Point(100,200);
pts[0][2] = Point(200,200);
pts[0][3] = Point(200,100);
pts[0][4] = Point(100,100);const Point* ppts[] = [pts[0]];
int npt[] = [5]; //个数
Scalar color = Scalar(255, 255, 12); //设置颜色
fillPoly(src, ppts, npt, 1, color, 8);//填充 cv::fillPoly
加文本text
putText(src, “Hello World”, Point (300, 300), CV_FONT_HERSHEY_COMPLEX(字体), 1.0,Scalar(0,0,255),1,8)
画随机的线 / RNG (随机数库)
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//先声明
void RandomlineDemo(Mat);
int main(){
Mat bgImage = imread("D:/timg.jpg");
RandomlineDemo(bgImage);
}
//再定义
void RandomlineDemo(Mat bgImage){
RNG rng(12345);
Point pt1;
Point pt2;
Mat bg = Mat::zeros(bgImage.size(), bgImage.type());
namedWindow("random line demo", CV_WINDOW_AUTOSIZE);
for (int i = 0; i<10000; i++){
pt1.x = rng.uniform(0, bg.cols);
pt2.x = rng.uniform(0, bg.cols);
pt1.y = rng.uniform(0, bg.rows);
pt2.y = rng.uniform(0, bg.rows);
Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255) );
if (waitKey(50) > 0)
break;
line(bg, pt1, pt2, color, 1, 8);
imshow("random line demo", bg);
}
}
图像模糊
均值模糊
(模板内权重一样的模糊)
blur(Mat src, Mat dst, Size(xradius, yradius),Point(-1,-1)(默认中心));
高斯模糊
(是一个抛物线的基于权重的模糊)
GaussianBlur(Mat src, Mat dst, Size(x, y),sigmaX, sigmaY);
Size(x, y) 必须是奇数
图像腐蚀与膨胀
膨胀:
需要图像A 和 结构元素B,
图像A 和 结构元素B,对应位置进行与运算,决定该像素位置的0或1是否保留
(结构元素B 在 图像A上移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值来替代锚点的像素,B为任意形状)
腐蚀相反
获取结构形状
getStructuringElement( int shape, Size ksize, Point anchor)
-形状(MORPH_RECT / MORPH_CROSS / MORPH_ELLIPSE)
-大小
-锚点 Point(-1, -1) 默认中心腐蚀
erode( src, dst, kernel )膨胀
dliate( src, dst, kernel )
动态调整结构元素大小
TrackBar createTrackbar( const String & tr ackbarname, const String winName, int* value, int count, Trackbarcallback func, void * userdata = 0)
下面代码生成图像+调整条(手动调整结构元素大小)
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
Mat src, dst;
char OUTPUT_WIN[] = "output image";
int element_size = 3;
int max_size = 21;
void CallBack_Demo(int , void*);
//int main( int argc, char** argv) {
int main() {
src = imread("D:/timg.jpg");
if (!src.data) {
printf("could not load image... \n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
createTrackbar("Element Size :" , OUTPUT_WIN, &element_size, max_size, CallBack_Demo);
CallBack_Demo(0,0);
waitKey(0);
return 0;
}
void CallBack_Demo(int, void*){
int s = element_size * 2 + 1;
Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));
dilate(src, dst, structureElement, Point(-1, -1), 1);
imshow(OUTPUT_WIN, dst);
return;
}
开 / 闭操作
开操作 - open
先腐蚀后膨胀 ,去掉小的对象,
假设背景黑色,有白色小点(白色小点消失)
(个人理解:图像去除毛刺)
相关API
morphologyEx( src, dest, CV_MOP_BLACKHAT, kernel );
int OPT – CV_MOP_OPEN/ CV_MOP_CLOSE/ CV_MOP_GRADIENT/ CV_MOP_TOPHAT/ CV_MOP_BLACKHAT 形态学操作类型
Mat kernel 结构元素
int Iteration 迭代次数,默认是1
闭操作 - close
先膨胀后腐蚀
可以填充小的洞,如下图,黑色背景
(个人理解:图像更饱满)
形态学梯度 - Morphological Gradient
膨胀减去腐蚀
又称基本梯度(其他还包括-内部梯度,方向梯度)
基本梯度:是用膨胀后的图像减去腐蚀后的图像得到差值图像,称为梯度图像也是OpenCV中支持的计算形态学梯度的方法,而此方法得到梯度有被称为基本梯度。
内部梯度:是用原图像减去腐蚀之后的图像得到差值图像,称为图像的内部梯度。
外部梯度:是用图像膨胀之后再减去原来的图像得到的差值图像,称为图像的外部梯度。
方向梯度:是使用X方向与Y方向的直线作为结构元素之后得到图像梯度,用X方向直线做结构元素分别膨胀与腐蚀之后得到图像求差值之后称为X方向梯度,用Y方向直线做结构元素分别膨胀与腐蚀之后得到图像求差值之后称为Y方向梯度。
顶帽 - top hat
原图像与开操作之间的差值图像
上左:原图像 。。。。。。。 上右:输出图像
黑帽
闭操作与原图像之间的差值图像
上左:原图像 。。。。。。。 上右:输出图像
上左:原图像 。。。。。。。。。。。上右:输出图像
#include <iostream>
#include <opencv2/opencv.hpp>
#include <cmath>
using namespace cv;
int main (){
Mat src, dst;
src = imread("D:/cat.jpg");
if (!src.data){
printf("could not load image...\n");
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
char output_title[] = "morphology demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
Mat kernel = getStructuringElement(MORPH_RECT, Size(40,40), Point(-1,-1));
// morphologyEx(src, dst, CV_MOP_OPEN, kernel);
// morphologyEx(src, dst, CV_MOP_GRADIENT, kernel);
// morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);
morphologyEx(src, dst, CV_MOP_BLACKHAT, kernel);
imshow(output_title, dst);
waitKey(0);
return 0;
}