OpenCV实现图像的灰度化->二值化->Canny边缘检测以及对比度(Contrast)和亮度(Brightness)值调整
图像灰度化:简单的来说就是使R,G,B value在阈值[0,255]间取得相同的值,总共有256个等级,黑白两种颜色其实可以看成是灰度化处于两个极端时的情形,中间254个等级分别代表灰度化的程度(浅深)。
图像二值化:简单的来说就是将图像上的像素点的灰度值设置为(0,0,0)(黑色)或(255,255,255)(白色),使图像只呈现出明显的黑白效果。
Canny算子:其目的是找到一个最优的边缘检测算法,使其满足三个主要的标准:
1.低错误率:标识出尽可能多的边缘,同时尽量减少噪声产生的影响;
2.高定位:标识出的边缘应与图像的实际边缘尽可能接近;
3.最小响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不应标识为边缘。
Canny边缘检测步骤:滤波->计算梯度幅值和方向->非极大值抑制(排除非边缘像素,保留候选边缘) (每个步骤的具体原理可参考OpenCV3编程入门这本书,百度一下pdf版应该就能找到,建议最好买一本,声明一下:绝对不是打广告 (●‘?‘●))。
亮度和对比度调整:首先应了解点操作(点算子)这个概念:根据输入像素值(有时可加上某些全局信息或参数),来计算输出像素的值。这类算子包括亮度和对比度调整,颜色校正(colorcorrection)和变换(transformations)。两种最常用的点操作满足下式:
g(i,j)=a*f(i,j)+b
(a控制对比度,b控制亮度,f(i,j)为源图像像素,g(i,j)为输出图像像素)
本Demo中也是使用三个for循环来执行图像亮度与对比度的调整。废话不多说,代码不会骗人,(●‘?‘●)。
工程代码如下:
//-----------------------------------【头文件包含部分】-----------------------------------------
// 描述:包含程序所依赖的头文件
//----------------------------------------------------------------------------------------------
#include <cv.h>
#include <highgui.h>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
//-----------------------------------【命名空间声明部分】--------------------------------------
// 描述:包含程序所使用的命名空间
//---------------------------------------------------------------------------------------------
using namespace std;
using namespace cv;
//-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量声明
//---------------------------------------------------------------------------------------------
int g_nContrastValue; //对比度值
int g_nBrightValue; //亮度值
int Thresh = 50;
//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//---------------------------------------------------------------------------------------------
static void ContrastAndBright(int);
void ShowHelpText();
//-----------------------------------【声明图像IplImage指针】----------------------------------
//描述:声明图像IplImage指针
//---------------------------------------------------------------------------------------------
IplImage* g_pSrcImg = NULL;
IplImage* g_pGrayImage = NULL;
IplImage* g_pCannyImg = NULL;
IplImage *g_pBinaryImage = NULL;
IplImage *g_pDstImage = NULL;
//滑动条响应函数
void onTrackerSlid(int thresh)
{
cvCanny(g_pGrayImage, g_pCannyImg, (float)thresh, (float)thresh * 3, 3);
cvShowImage("Canny Image", g_pCannyImg);
}
//-----------------------------【on_trackbar( )函数】------------------------------------
// 描述:图像二值化阈值回调函数
//-----------------------------------------------------------------------------------------------
void on_trackbar(int pos)
{
// 转为二值图
cvThreshold(g_pGrayImage, g_pBinaryImage, pos, 255, CV_THRESH_BINARY);
// 显示二值图
cvShowImage("Binary Image", g_pBinaryImage);
}
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
system("color 5F");
ShowHelpText();
if (argc != 2)
argv[1] = "1.jpg";
//设定对比度和亮度的初值
g_nContrastValue = 80;
g_nBrightValue = 80;
//载入图像,强制转化为Gray
if ((g_pSrcImg = cvLoadImage(argv[1], 1)) != 0)
{
cout << "Press ESC to Quit" << endl;
//将颜色空间由RGB转化为Gray
g_pGrayImage = cvCreateImage(cvGetSize(g_pSrcImg), 8, 1);
cvCvtColor(g_pSrcImg, g_pGrayImage, CV_RGB2GRAY);
// 创建二值图
g_pBinaryImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);
//canny边缘检测
g_pCannyImg = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);
cvNamedWindow("ContrastandBrightnessWnd", CV_WINDOW_AUTOSIZE);
//创建轨迹条
cvCreateTrackbar("Contrast:", "ContrastandBrightnessWnd", &g_nContrastValue, 300, ContrastAndBright);
cvCreateTrackbar("Brightness:", "ContrastandBrightnessWnd", &g_nBrightValue, 200, ContrastAndBright);
//调用回调函数
ContrastAndBright(g_nContrastValue);
ContrastAndBright(g_nBrightValue);
//创建窗口
cvNamedWindow("Source Image", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Gray Image", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Canny Image", CV_WINDOW_AUTOSIZE);
cvNamedWindow("Binary Image", CV_WINDOW_AUTOSIZE);
// 滑动条
int nThreshold = 0;
cvCreateTrackbar("Threshold:", "Binary Image", &nThreshold, 254, on_trackbar);
on_trackbar(1);
//添加滑动条来调节边缘检测的阈值
onTrackerSlid(Thresh);
cvShowImage("Gray Image", g_pCannyImg);
cvCreateTrackbar("Threshold", "Canny Image", &Thresh, 300, onTrackerSlid);
//显示图像
cvShowImage("Source Image", g_pSrcImg);
cvShowImage("Gray Image", g_pGrayImage);
//保存图像
cvSaveImage("Gray_Image.jpg", g_pGrayImage);
cvSaveImage("Canny_Image.jpg", g_pCannyImg);
cvSaveImage("Binary Image.jpg", g_pBinaryImage);
//等待按"ESC"键退出
while (1)
if (cvWaitKey(100) == 27)
break;
//销毁窗口
cvWaitKey(0);
cvDestroyWindow("Source Image");
cvDestroyWindow("Canny Image");
cvDestroyWindow("Gray Image");
cvDestroyWindow("Binary Image");
//释放图像
cvReleaseImage(&g_pGrayImage);
cvReleaseImage(&g_pCannyImg);
cvReleaseImage(&g_pSrcImg);
cvReleaseImage(&g_pBinaryImage);
return 0;
}
return -1;
}
//-----------------------------【ContrastAndBright( )函数】------------------------------------
// 描述:改变图像对比度和亮度值的回调函数
//---------------------------------------------------------------------------------------------
static void ContrastAndBright(int)
{
// 三个for循环,执行运算 dstImg(i,j) = a*srcImg(i,j) + b
Mat srcImg, dstImg;
srcImg = imread("lena.jpg");
if (!srcImg.data)
{
printf("读取srcImg图片错误~! \n");
return ;
}
dstImg = Mat::zeros(srcImg.size(), srcImg.type());
for (int y = 0; y < srcImg.rows; y++)
{
for (int x = 0; x <srcImg.cols; x++)
{
for (int c = 0; c < 3; c++)
{
dstImg.at<Vec3b>(y, x)[c] = saturate_cast<uchar>((g_nContrastValue*0.01)*(srcImg.at<Vec3b>(y, x)[c]) + g_nBrightValue);
}
}
}
// 显示图像
imshow("ContrastandBrightnessWnd", dstImg);
}
//-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
printf("\n\n\t\t\t 运行平台为win32 VS2013\n");
printf("\n\n\t\t\t OpenCV一个值得你学习的强大视觉库\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ------------------------------------------------------------------------------------------------------------------\n");
}
程序运行结果
作者目前还是个小菜鸟,如有错误,请指出来,相互交流一下,(●‘?‘●)。