图像处理涉及的方面十分广泛,具体的方法种类也比较多,传统图像处理技术主要集中在图像的获取 、变换、增强、回复、压缩、分割、边缘检测等方面。随着新工具,新技术的不断出现,这些图像处理方法也在不断更新与发展。接下来讲解一些基础的图像操作。
一:对图像像素点进行操作
对图像像素点进行操作就是对灰度值进行操作,实际实现时先获得目标图像的灰度值,然后再对 灰度值进行数学操作,即可实现,具体代码如下:
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src = imread("F:/dog.jpg");
namedWindow("input", CV_WINDOW_AUTOSIZE);//创建窗口 可以不用创建
imshow("input", src);//显示原图像
Mat gray_src;//定义一个新的图像
cvtColor(src, gray_src, CV_BGR2GRAY);//将原图像转换成灰度图像
namedWindow("output", CV_WINDOW_AUTOSIZE);//创建窗口
imshow("output", gray_src);//显示灰度图像
Mat g = gray_src.clone();//克隆新图,将灰度图像cope过来
int height = gray_src.rows;//获取图像的高度
int width = gray_src.cols;//获取图像的宽度
for (int row = 0; row < height; row++)//for循环语句
{
for (int clo = 0; clo < width; clo++)
{
int gray = gray_src.at(row, clo);//获取图像的像素值
g.at(row, clo) = 255 - gray;//对图像的像素值进行数值操作
}
}
imshow("【翻转图】", g);
Mat dst;
dst.create(src.size(), src.type());//定义一个新的图像类,尺寸与类型类似于cope
int heights = src.rows;
int widths = src.cols;
int nc = src.channels();//获取通道数,这里是一个三通道图像
for (int row = 0; row < heights; row++)
{
for (int col = 0; col < widths; col++)
{
int b = src.at(row, col)[0];//获取原图像的b通道像素值
int g = src.at(row, col)[1];//获取原图像的g通道像素值
int r = src.at(row, col)[2];//获取原图像的r通道像素值
dst.at(row, col)[0] = 255 - b;//对图像像素值进行数值操作
dst.at(row, col)[1] = 255 - g;
dst.at(row, col)[2] = 255 - r;
}
imshow("【多通道】", dst);
}
waitKey(0);
return 0;
}
二:调整图像的亮度和对比度
有时候我们在对图像进行操作时也会用到调整对比度和亮度等,同样需要对图像的灰度值进行操作,具体代码如下:
#include
#include
using namespace cv;
int main()
{
Mat src, dst;
src = imread("F:/girl.png");//读入一副图像
char input_win[] = "input image";//创建一个显示框
namedWindow(input_win, CV_WINDOW_NORMAL);
cvResizeWindow(input_win, 500, 500);//设置显示窗口大小
imshow(input_win, src);
int height = src.rows;//获取图像的参数,高度,宽度,通道数
int width = src.cols;
int n = src.channels();
dst = Mat::zeros(src.size(), src.type());//创建一个和原图像大小 类型相同的空白图像
float alpha = 1.0;//设置阿尔法值
float bata = 50;//设置贝塔值
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
if (n == 1)//单通道的调整对比度亮度
{
float a = src.at(row, col);
dst.at(row, col) = saturate_cast(a*alpha + bata);//公式
}
else if (n == 3)//3通道的对比度亮度调整
{
float b = src.at(row, col)[0];//bule
float g = src.at(row, col)[1];//green
float r = src.at(row, col)[2];//rad
dst.at(row, col)[0] = saturate_cast(b*alpha + bata);
dst.at(row, col)[1] = saturate_cast(g*alpha + bata);
dst.at(row, col)[2] = saturate_cast(r*alpha + bata);
}
}
}
char output_title[] = "this is a gril";//显示窗口抬头设置
namedWindow(output_title, CV_WINDOW_NORMAL);
cvResizeWindow(output_title, 500, 500);//设置显示窗口大小
imshow(output_title, dst);//显示出处理过后的图像
waitKey(0);
return 0;
}
三:绘制图形与文字
在实际的图像处理中,有时候需要我们在目标图像上绘制一些图形或者是写一些文字,例如在捕捉人脸时,需要绘制一个圆进行捕捉,下面代码即可实现在图像上绘制图形以及文字:
#include
#include
#include
#include
using namespace cv;
Mat mygirl;//定义全局变量
void mylines();//声明函数
void myRectangle();//声明一个无返回值的矩形函数
void myellipse();//声明一个无返回值的椭圆函数
void mycircle();//声明一个无返回值的圆函数
int main()
{
mygirl = imread("F:/openCV/girl.png");
mylines();//调用直线函数
myRectangle();//调用矩形函数
myellipse();//调用椭圆函数
mycircle();//调用圆函数
putText(mygirl, "Hello openCV", Point(100, 100), CV_FONT_BLACK, 2.0, Scalar(12, 23, 200), 3, LINE_8);//CV_FONNT为字体类型,后面2.0为字体大小,3为字体粗细,8为line_8
namedWindow("optput", CV_WINDOW_AUTOSIZE);//定义显示窗口
imshow("optput", mygirl);//显示输出图像
waitKey(0);
return 0;
}
void mylines()//定义函数
{
Point p1 = Point(200, 200);//第一个点的坐标
Point p2;//另外一种表示方法
p2.x = 400;
p2.y = 400;
Scalar color = Scalar(0, 0, 255);//直线的颜色定义 也可用Scalar(0,0,255)直接表示
line(mygirl, p1, p2, color, 1, LINE_AA);
//将直线画到图像上面 1是指线的粗细
//int thickness = 1;
//int linetype = 8;等于LINE_8,LINE_AA的意思是无锯齿直线
//可以替换成line(mygirl,p1,p2,color,thickness,linetype);
}
void myRectangle()//定于矩形函数
{
Rect rect = Rect(200, 250, 200, 250);//矩形的四个边
Scalar color = Scalar(255, 0, 0);
rectangle(mygirl, rect, color, 2, LINE_8);
}
void myellipse()//定义椭圆函数
{
Scalar color = (0, 255, 0);//设置颜色
ellipse(mygirl, Point(mygirl.rows / 2, mygirl.cols / 2), Size(mygirl.rows / 2, mygirl.cols / 2),90,0,360,2,LINE_AA);
//Point为椭圆的原点位置:可以写成Point center = Point(mygirl.row/2,mygirl.col/2);
//size为椭圆的尺寸大小
//90为偏移的角度 偏移了90度
//0到360是扩展的弧度 ,180是个半椭圆 360是一个封闭的椭圆;
}
void mycircle()//定义一个圆函数
{
Scalar color = Scalar(0, 255, 255);
Point center = Point(mygirl.rows / 2, mygirl.cols / 2);
circle(mygirl, center, 150, color, 2, LINE_8);
//150是半径,可以是数字 ,也可以用上面表示圆的原点方法表示
//当thickness = -1时为实习圆,当为负数时为实心。
}
void myPolygon()
{
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* ptts[] = { pts[0] };
int npt[] = { 5 };
Scalar color = Scalar(255, 12, 255);
fillPoly(mygirl, ppts,npt, 1, color, 8);
}
四:生成随机线
图像图例中,产生随机数是一个常用的手段,代码如下:
#include
#include
using namespace cv;
void RandomLineDemo();//声明随机函数
int main()
{
RandomLineDemo();//调用随机函数
waitKey(0);
return 0;
}
void RandomLineDemo()//定义随机函数
{
RNG rng(12345);//随机范围
Point pt1;//定义随机的两个点
Point pt2;//第二个点
Mat bg(500, 500, CV_8UC3, Scalar(0, 0, 0));//绘制一个空白图像
for (int i = 0; i < 100000; i++)//for循环
{
pt1.x = rng.uniform(0, 500);//定义第一个点的X坐标
pt1.y = rng.uniform(0, 500);//定义第一个点的Y坐标
pt2.x = rng.uniform(0, 500);//定义第二个点的X坐标
pt2.y = rng.uniform(0, 500);//定义第二个点的Y坐标
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));//设置颜色的随机范围
line(bg, pt1, pt2, color, 1, LINE_8);//将随机产生的直线绘制到空白图像上
namedWindow("output", CV_WINDOW_AUTOSIZE);
imshow("output", bg);
if (waitKey(50) > 0)//设置停止时间
{
break;
}
}
}