//-----------------------------------OpenCV学习-------------------------------------
// 程序名称:OpenCV程序模板样式
// 所用IDE版本: Visual Studio 2013
// 开发所用OpenCV版本: 2.4.9
// 2016年10月 Created by 孙立波
//包含程序所依赖的头文件:为方便起见把经常用的头文件都写在这里(前三必须包含),也可以用#include "opencv.hpp"包含下面所有头文件
#include <opencv2\core\core.hpp> //程序库核心功能,基本数据与结构和算法函数
#include <opencv2\imgproc\imgproc.hpp> //包含主要的图像处理函数
#include <opencv2\highgui\highgui.hpp> //包含图像、视频读写函数和部分用户界面函数
//出现#include "cv.h"表示老式风格,并包含老式所有头文件
//#include <opencv2\features2d\features2d.hpp> //包含特征点检测器、描述子及特征点匹配框架
//#include <opencv2\nonfree\nonfree.hpp> //SURF和SIFT会用到
#include <iostream>
//包含程序所使用的命名空间
using namespace cv; //opencv2的名字空间
using namespace std;
//描述:控制台应用程序的入口函数,程序从这里开始执行??
int main(int argc, char** argv) //argv相当于"行"指针
{
return 0;
}
//-----------------------------------OpenCV学习1-------------------------------------
// 程序名称:测试读入图片并显示
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("D:\\workplace\\opencv_training\\test1.png");
if (img.empty())
{
cout << "error";
return -1; //调试程序框会显示返回值结果
}
imshow("mytest1", img);
waitKey(); //只有前面生成GUI窗口,waitKey才起作用
//如果前面运行失败,还想看控制台窗口输出,可以在return前system("pause");
return 0;
}
//-----------------------------------OpenCV学习2-------------------------------------
// 程序名称:用老版的OpenCV1测试读入图片并显示
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <cv.h>
#include <highgui.h>
using namespace std;
int main()
{
IplImage * test;
test = cvLoadImage("D:\\workplace\\opencv_training\\test1.png");//图片路径
cvNamedWindow("mytest1", 1);
cvShowImage("mytest1", test);
cvWaitKey(0);
cvDestroyWindow("mytest1");
cvReleaseImage(&test); //因为是用new动态生成的静态内存空间
return 0;
}
//-----------------------------------OpenCV学习3-------------------------------------
// 程序名称:翻转图片并显示和保存
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main()
{
Mat img1 = imread("D:\\workplace\\opencv_training\\test1.png");
if (img1.empty())
{
cout << "error:图像未装载成功";
system("pause");
return -1; //调试程序框会显示返回值结果
}
imshow("mytest1", img1);
Mat img2;
flip(img1,img2,1);//正数表示水平,0表示垂直,负数表示水平和垂直都翻转
imshow("mytest2", img2);
waitKey(0); //只有前面生成GUI窗口,waitKey才起作用
//如果前面运行失败,还想看控制台窗口输出,可以在return前system("pause");
imwrite("output.bmp",img2);//保存翻转后的图像,再如imwrite("D:\\output.bmp",img2);
return 0;
}
//-----------------------------------OpenCV学习4-------------------------------------
// 程序名称:翻转图片写入原内存,并以读入转化方式生成灰度和彩色图像分别显示
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main()
{
Mat img1 = imread("D:\\workplace\\opencv_training\\test1.png");
if (img1.empty())
{
cout << "error:图像未装载成功";
system("pause");//使控制台界面保留
return -1; //调试程序框会显示返回值结果
}
imshow("mytest1", img1);
Mat img2;
flip(img1,img1,1);//翻转结果给原内存,正数表示水平,0表示垂直,负数表示水平和垂直都翻转
imshow("mytest2", img1);
//得到原图像的灰度图像,宏定义值为0,注:负数或不填写即为原格式输入到内存
Mat img3 = imread("D:\\workplace\\opencv_training\\test1.png",CV_LOAD_IMAGE_GRAYSCALE);
//得到原图像的彩色图像,宏定义值为1
Mat img4 = imread("D:\\workplace\\opencv_training\\test1.png",CV_LOAD_IMAGE_COLOR);
imshow("mytest3", img3);
imshow("mytest4", img4);
waitKey(0); //只有前面生成GUI窗口,waitKey才起作用
//如果前面运行失败,还想看控制台窗口输出,可以在return前system("pause");
return 0;
}
//-----------------------------------OpenCV学习5-------------------------------------
// 程序名称:用cv开头可以节省时间,深入了解Mat数据类型相关用法
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
// 复制构造函数和赋值运算符只会赋值Mat的头部,copyTo和clone是深复制
// 不同数据类型Mat的复制用convertTo(通道数必须相同)
// create方法要看是否与原来的大小和类型相同来决定是否重分配数据块
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
// 测试函数用于在内存返回一个自创建大小500*500、像素值50的灰度值图像
Mat function()
{
// 用构造函数create image
Mat ima(500, 500, CV_8U, 50);
// return it
return ima;
}
int main()
{
// 创建一个240*320的值都为100的灰度图像并显示,观察效果后运行下一步程序
Mat image1(240, 320, CV_8U, 100);
// or:Mat image1(240,320,CV_8U,cv::Scalar(100));
imshow("Image0", image1);
waitKey(0);
// create方法要看是否与原来的大小和类型相同来决定是否重分配数据块,实例:
// 用create方法重建一个大小和值不同的灰度图像,并显示,观察效果后运行下一步程序
image1.create(200, 200, CV_8U);
image1 = 200;
imshow("Image00", image1);
waitKey(0);
// 用构造函数创建一个红色的彩色图像,大小为240*320,并显示,观察效果后运行下一步程序
Mat image2(240, 320, CV_8UC3, cv::Scalar(0, 0, 255));
// or:Mat image2(Size(320,240),CV_8UC3);image2= Scalar(0,0,255);
imshow("Image2", image2);
waitKey(0);
// 读取图像用法!!
Mat image= imread("D:\\workplace\\opencv_training\\test1.png");
Mat image3;
image.copyTo(image3);
Mat image4 = image.clone();
//显示源图像的拷贝与复制的图像,观察效果后运行下一步程序
imshow("Image 3", image3);
imshow("Image 4", image4);
waitKey(0);
// 从程序定义的图像创建函数法获取一个灰度图像,500*500像素,观察效果后运行下一步程序
Mat gray = function();
imshow("Image 5", gray);
waitKey(0);
//读取一个原图像以灰度图像给内存,在数据类型不一样情况下,用convertTo方法,观察效果
Mat image5= imread("D:\\workplace\\opencv_training\\test1.png", CV_LOAD_IMAGE_GRAYSCALE);
// convert the image into a floating point image [0,1]浮点型图像
Mat image6;
image5.convertTo(image6, CV_32F, 1 / 255.0, 0.0);
imshow("Image 6", image6);
waitKey(0);
return 0;
}
//-----------------------------------OpenCV学习6-------------------------------------
// 程序名称:ROI设置和掩码操作实例
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
int main()
{
cv::Mat image = cv::imread("D:\\workplace\\opencv_training\\test2.png");
// read the logo
cv::Mat logo = cv::imread("D:\\workplace\\opencv_training\\test1.png");
// 以左上角为位置起点,构建原图像中数据区的logo映射区
cv::Mat imageROI(image,
cv::Rect(image.cols - logo.cols, //ROI coordinates
image.rows - logo.rows,
logo.cols, logo.rows));// ROI size
// 在ROI区域插入logo像素值
logo.copyTo(imageROI);
cv::imshow("Image", image);
cv::waitKey(0); // wait for a key pressed
// re-read the original image注意此时图像是未处理的原图像无ROI
image = cv::imread("D:\\workplace\\opencv_training\\test2.png");
// define image ROI at image bottom-right
imageROI = image(cv::Rect(image.cols - logo.cols, image.rows - logo.rows,
logo.cols, logo.rows));
// or using ranges:
// imageROI= image(cv::Range(image.rows-logo.rows,image.rows),
// cv::Range(image.cols-logo.cols,image.cols));
// use the logo as a mask (must be gray-level)将logo做掩码其中掩码像素值为零的复制不到ROI
cv::Mat mask1(logo);
// insert by copying only at locations of non-zero mask
logo.copyTo(imageROI, mask1);
cv::imshow("Image1", image); // show the image
cv::waitKey(0); // wait for a key pressed
//让掩码图像即logo值全为0,查看结果图像
logo = 0;
image = cv::imread("D:\\workplace\\opencv_training\\test2.png");
imageROI = image(cv::Rect(image.cols - logo.cols, image.rows - logo.rows,
logo.cols, logo.rows));
cv::Mat mask2(logo);
logo.copyTo(imageROI, mask2);
cv::imshow("Image2", image); // 结果应显示,原图像无变化!
cv::waitKey(0);
return 0;
}
//-----------------------------------OpenCV学习7-------------------------------------
// 程序名称:在图像上左键点击响应为像素位置灰度值、翻转图像和在图像上绘图
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
//回调函数设置响应内容
void onMouse(int event, int x, int y, int flags, void* param)
{
cv::Mat *im = reinterpret_cast<cv::Mat*>(param);
switch (event)
{ // 调度事件列表及应响应的操作
case CV_EVENT_LBUTTONDOWN: // 鼠标左键按下事件
// display pixel value at (x,y)
{
std::cout << "at (" << x << "," << y << ") value is: "
<< int(im->at<uchar>(cv::Point(x, y))) << std::endl;
break;
}
}
}
int main()
{
cv::Mat image; // 创建图像实例,看默认下构造函数分配的行列
std::cout << "This unread empty image is " << image.rows << " x "
<< image.cols << std::endl;
// read the input image as a gray-scale image
image = cv::imread("D:\\workplace\\opencv_training\\test1.png", CV_LOAD_IMAGE_GRAYSCALE);
if (image.empty())
{
std::cout << "Error reading image..." << std::endl;
return 0;
}
// 读取图像的行列和通道显示出来
std::cout << "This reading image is " << image.rows << " x "
<< image.cols << std::endl;
std::cout << "This image has "
<< image.channels() << " channel(s)" << std::endl;
cv::imshow("OriginalImage", image); // show the image
//利用鼠标回调函数的激活函数,建立显示图像的窗口和回调函数的关联,点击窗口内像素点即显示出来
cv::setMouseCallback("OriginalImage", onMouse, reinterpret_cast<void*>(&image));
cv::waitKey(0);
//翻转图像
cv::Mat result; // we create another empty image
cv::flip(image, result, 1); // 水平翻转原图像到结果图像
// 0 for vertical,
// negative for both
cv::namedWindow("FlipOutput Image"); // the output window
cv::imshow("FlipOutput Image", result);
cv::waitKey(0); // 0 to indefinitely wait for a key pressed
// specifying a positive value will wait for
// the given amount of msec
// 自创建一个空的图像窗口,装载图像后可以画图和添加文本
cv::namedWindow("Drawing on an Image"); // define the window
cv::circle(image, // 源图像
cv::Point(155, 110), // 圆的中心坐标,单位:像素
65, // 半径
0, // 线的颜色 (0代表黑色)
3); // 线粗
cv::putText(image, // 在已画圆的图像上操作
"This is a dog.", // 所添加的text
cv::Point(40, 200), // 文本位置坐标,单位:像素
cv::FONT_HERSHEY_PLAIN, // 文本字体类型
2.0, // 字号
255, // 文本字体颜色 (here white)
2); // 文本厚度
cv::imshow("Drawing on an Image", image); // show the image
cv::waitKey(0); // 0 to indefinitely wait for a key pressed
return 0;
}
//-----------------------------------OpenCV学习8(i,j写反了,导致程序运行不过去)-------------
// 程序名称:在图像上加入椒盐噪声
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
#include <stdlib.h> // for std::rand!!!这个很关键
using namespace cv;
using namespace std;
//椒盐噪声函数,采用for循环
void salt1(Mat image, int n) //n为椒盐噪声点的个数
{
int i, j;
for (int k = 0; k < n; k++)
{
i = rand() % image.cols;//!!!!!!!!!!!!!!!!当时把i,j写反了,导致程序运行不过去。。。
j = rand() % image.rows;
if (image.type() == CV_8UC1)
{
image.at<uchar>(j, i) = 255;
}
else if (image.type() == CV_8UC3)
{
image.at<Vec3b>(j, i)[0] = 255;
image.at<Vec3b>(j, i)[1] = 255;
image.at<Vec3b>(j, i)[2] = 255;
}
}
}
// 下面的函数说明Mat_类的operator()方法比at()简单
//This is an extra version of the function
// to illustrate the use of cv::Mat_
// works only for a 1-channel image
void salt2(cv::Mat image, int n)
{
// use image with a Mat_ template
cv::Mat_<uchar> im2(image);
// or with references:
// cv::Mat_<uchar>& im2= reinterpret_cast<cv::Mat_<uchar>&>(image);
int i, j;
for (int k = 0; k<n; k++)
{
// rand() is the MFC random number generator
i = rand() % image.cols;
j = rand() % image.rows;
if (im2.type() == CV_8UC1)
{
im2(j, i) = 255;// gray-level image
}
}
}
int main()
{
Mat image = imread("D:\\workplace\\opencv_training\\test3.jpg");
if (image.empty())
{
cout << "error:图像未装载成功";
system("pause");//使控制台界面保留
return -1; //调试程序框会显示返回值结果
}
imshow("Image", image);
waitKey();
salt1(image, 3000);
imshow("Salt_Image", image);
waitKey();
//重新将源图像的灰度图像格式装入内存,测试对灰度图像加噪点的salt2函数
Mat image1 = imread("D:\\workplace\\opencv_training\\test3.jpg", 0);
salt2(image1, 3000);
imshow("Salt_Image2", image1);
waitKey();
return 0;
}
//-----------------------------------OpenCV学习9-------------------------------------
// 程序名称:用函数和重载运算符加权两个图像和将某图像一通道加权到一个图像再融合
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
cv::Mat image1=imread("D:\\workplace\\opencv_training\\test3.jpg");
cv::Mat image2 =imread("D:\\workplace\\opencv_training\\test4.jpg");
if (!image1.data)
return 0;
if (!image2.data)
return 0;
cv::imshow("Image 1", image1);
cv::imshow("Image 2", image2);
cv::waitKey();
cv::Mat result;
// 加权两个图像,显示效果
cv::addWeighted(image1, 0.7, image2, 0.9, 0., result);
cv::imshow("result", result);
cv::waitKey();
// 使用重载运算符加权两个图像
result = 0.7*image1 + 0.9*image2;
cv::imshow("result with operators", result);
image2 = cv::imread("D:\\workplace\\opencv_training\\test3.jpg", 0);
cv::waitKey();
//将某图像一通道加权到一个图像再融合
std::vector<cv::Mat> planes;// create vector of 3 images
// split 1个 3-channel image into 3个 1-channel images
cv::split(image1, planes);
// add to blue channel
planes[0] += image2;
// merge the 3 1-channel images into 1 3-channel image
cv::merge(planes, result);
cv::imshow("Result on blue channel", result);
cv::waitKey();
return 0;
}
//-----------------------------------OpenCV学习10-------------------------------------
// 程序名称:测试几个锐化函数,看哪个运行效率高且简单
// 实验证明:第三个采用了现成的滤波函数,但是模板核自己要做好的那个最好
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
#include <vector>
using namespace cv;
using namespace std;
//锐化函数,该函数可以处理彩色图像
void sharpen(const cv::Mat &image, cv::Mat &result) {
result.create(image.size(), image.type()); // allocate if necessary
int nchannels = image.channels();
for (int j = 1; j<image.rows - 1; j++) { // for all rows (except first and last)
const uchar* previous = image.ptr<const uchar>(j - 1); // previous row
const uchar* current = image.ptr<const uchar>(j); // current row
const uchar* next = image.ptr<const uchar>(j + 1); // next row
uchar* output = result.ptr<uchar>(j); // output row
for (int i = nchannels; i<(image.cols - 1)*nchannels; i++) {
*output++ = cv::saturate_cast<uchar>(5 * current[i]
- current[i - nchannels] - current[i + nchannels] - previous[i] - next[i]);
//output[i]= cv::saturate_cast<uchar>
//(5*current[i]-current[i-nchannels]-current[i+nchannels]-previous[i]-next[i]);
}
}
// Set the unprocess pixels to 0
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows - 1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols - 1).setTo(cv::Scalar(0));
}
//同样的锐化函数,但是使用了迭代器,该函数只能处理灰度图像
// this one works only for gray-level image
void sharpenIterator(const cv::Mat &image, cv::Mat &result) {
cv::Mat_<uchar>::const_iterator it = image.begin<uchar>() + image.cols;
cv::Mat_<uchar>::const_iterator itend = image.end<uchar>() - image.cols;
cv::Mat_<uchar>::const_iterator itup = image.begin<uchar>();
cv::Mat_<uchar>::const_iterator itdown = image.begin<uchar>() + 2 * image.cols;
result.create(image.size(), image.type()); // allocate if necessary
cv::Mat_<uchar>::iterator itout = result.begin<uchar>() + result.cols;
for (; it != itend; ++it, ++itout, ++itup, ++itdown) {
*itout = cv::saturate_cast<uchar>(*it * 5 - *(it - 1) - *(it + 1) - *itup - *itdown);
}
// Set the unprocess pixels to 0
result.row(0).setTo(cv::Scalar(0));
result.row(result.rows - 1).setTo(cv::Scalar(0));
result.col(0).setTo(cv::Scalar(0));
result.col(result.cols - 1).setTo(cv::Scalar(0));
}
//使用现成的滤波函数,但是模板核自己要做好
void sharpen2D(const cv::Mat &image, cv::Mat &result) {
// Construct kernel (all entries initialized to 0)
cv::Mat kernel(3, 3, CV_32F, cv::Scalar(0));
// assigns kernel values
kernel.at<float>(1, 1) = 5.0;
kernel.at<float>(0, 1) = -1.0;
kernel.at<float>(2, 1) = -1.0;
kernel.at<float>(1, 0) = -1.0;
kernel.at<float>(1, 2) = -1.0;
//filter the image
cv::filter2D(image, result, image.depth(), kernel);
}
int main()
{
cv::Mat image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg");
if (!image.data)
return 0;
cv::Mat result;
//记录第一个锐化函数时间,输出效果
double time = static_cast<double>(cv::getTickCount());
sharpen(image, result);
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency();
std::cout << "time= " << time << std::endl;
cv::imshow("Image", result);
//记录第二个锐化函数时间,输出效果
// open the image in gray-level
image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg", 0);
time = static_cast<double>(cv::getTickCount());
sharpenIterator(image, result);
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency();
std::cout << "time 3= " << time << std::endl;
cv::imshow("Sharpened Image", result);
//记录第三个锐化函数时间,输出效果
image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg");
time = static_cast<double>(cv::getTickCount());
sharpen2D(image, result);
time = (static_cast<double>(cv::getTickCount()) - time) / cv::getTickFrequency();
std::cout << "time 2D= " << time << std::endl;
cv::imshow("Image 2D", result);
cv::waitKey();
return 0;
}
//-----------------------------------OpenCV学习11-------------------------------------
// 程序名称:重映射函数remape举例!!!只能应用于灰度图像
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
using namespace cv;
using namespace std;
// 使图像产生波动效果
void wave(const cv::Mat &image, cv::Mat &result) {
// the map functions
cv::Mat srcX(image.rows, image.cols, CV_32F); // x-map
cv::Mat srcY(image.rows, image.cols, CV_32F); // y-map
//映射参数像素坐标之间关系的建立,注:不是灰度值!
for (int i = 0; i<image.rows; i++) {
for (int j = 0; j<image.cols; j++) {
srcX.at<float>(i, j) = j;
srcY.at<float>(i, j) = i + 3 * sin(j / 6.0);
// horizontal flipping
// srcX.at<float>(i,j)= image.cols-j-1;
// srcY.at<float>(i,j)= i;
}
}
// // 应用映射函数!!!!!!!remape
cv::remap(image, // source image
result, // destination image
srcX, // x map
srcY, // y map
cv::INTER_LINEAR); // interpolation method
}
int main()
{
cv::Mat image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg", 0);//0代表只能用其灰度图像
// image is resize for book printing
cv::resize(image, image, cv::Size(), 0.6, 0.6);//把图像变成原来的0.6倍
cv::imshow("Image", image);
cv::Mat result;
wave(image, result);
cv::imshow("Remapped image", result);
cv::waitKey();
return 0;
}
//-----------------------------------OpenCV学习12-------------------------------------
// 程序名称:自定义类colordetector,分别用类成员函数RGB空间像素检测和仿函数实现Lab颜色空间像素检测
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
#include "colordetector.h"//需要定义该类的头文件(小段函数定义放在头文件)和类外成员函数定义(较长的函数体)
int main()
{
// 1. Create image processor object
ColorDetector cdetect;
// 2. Read input image
cv::Mat image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg");
if (image.empty())
return 0;
// 3. Set input parameters
cdetect.setTargetColor(230, 190, 130); // here blue sky
// 4. Process the image and display the result
cv::namedWindow("result");
cv::imshow("result", cdetect.process(image));
// or using functor使用函数对象或者仿函数
ColorDetector colordetector(230, 190, 130, // color
45, true); // Lab threshold,true代表使用Lab颜色空间
cv::namedWindow("result (functor)");
cv::imshow("result (functor)", colordetector(image));//对象调用了operator()运算符成员函数
cv::waitKey();
return 0;
}
//-----------------------------------OpenCV学习13-------------------------------------
// 程序名称:自定义控制器类进行GUI和模型之间的通信!!!,实现对用户的封装
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
using namespace std;
#include "colorDetectController.h"//控制器类完成GUI和模型之间的通信!!!
int main()
{
// Create the controller
ColorDetectController controller;
// To display the result
cv::namedWindow("Image");
// The following code simulate a user Interface
// based on the use of a controller
// Interaction with user is simply done
// using key pressed
std::cout << "q: to quit" << std::endl;
std::cout << "f: to input a filename" << std::endl;
std::cout << "t: to input target color values" << std::endl;
std::cout << "c: to input color distance threshold" << std::endl;
std::cout << "v: to view the different parameter values" << std::endl;
std::cout << "r: to run" << std::endl;
char key = ' ';
std::string filename;
while ((key = getchar()) != 'q') {
switch (key) {
uchar r, g, b;
case 'f': // read an image
std::cout << std::endl << "Filename? ";
std::cin >> filename;
std::cout << std::endl;
if (controller.setInputImage(filename))
std::cout << "...image successfully opened" << std::endl;
else
std::cout << "...cannot find image: " << filename << std::endl;
break;
case 't': // input target color
int ir, ig, ib;
std::cout << std::endl << "Target color? ";
std::cin >> ir >> ig >> ib;
std::cout << std::endl;
controller.setTargetColor(ir, ig, ib);
break;
case 'c': // input threshold
int th;
std::cout << std::endl << "Color distance threshold? ";
std::cin >> th;
std::cout << std::endl;
controller.setColorDistanceThreshold(th);
break;
case 'v': // view the parameters
std::cout << std::endl << "Image name: " << filename << std::endl;
controller.getTargetColour(r, g, b);
std::cout << std::endl << "Target color: "
<< static_cast<int>(r) << ","
<< static_cast<int>(g) << ","
<< static_cast<int>(b) << std::endl;
std::cout << std::endl << "Distance thresdhold: " << controller.getColorDistanceThreshold() << std::endl;
std::cout << std::endl;
break;
case 'i': // show input image
cv::imshow("Image", controller.getInputImage());
cv::waitKey(10); // for window to repaint
break;
case 'r': // run color detection
controller.process();
cv::imshow("Image", controller.getLastResult());
cv::waitKey(10); // for window to repaint
break;
}
}
return 0;
}
// ---------------------------------- - OpenCV学习14------------------------------------ -
// 程序名称:显示HSV个通道图像和利用色调和饱和度的数值区间做掩膜,实现人脸初步检测
// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)
#include <opencv2\opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
void detectHScolor(const cv::Mat& image, // 输入源图像
double minHue, double maxHue, // Hue interval
double minSat, double maxSat, // saturation interval
cv::Mat& mask) // 输出掩码
{
//将原图像先转换到 HSV 颜色空间
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);
// 分割3通道的hsv图像到3个独立矩阵对象
std::vector<cv::Mat> channels;
cv::split(hsv, channels);
// channels[0] is the Hue
// channels[1] is the Saturation
// channels[2] is the Value
// 色调掩码的构建
cv::Mat mask1; // under maxHue
cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);
cv::Mat mask2; // over minHue
cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);
cv::Mat hueMask; // hue mask
if (minHue < maxHue)
hueMask = mask1 & mask2;
else // if interval crosses the zero-degree axis
hueMask = mask1 | mask2;
// 饱和度掩码构建
// under maxSat
cv::threshold(channels[1], mask1, maxSat, 255, cv::THRESH_BINARY_INV);
// over minSat
cv::threshold(channels[1], mask2, minSat, 255, cv::THRESH_BINARY);
cv::Mat satMask; // saturation mask
satMask = mask1 & mask2;
// 色调和饱和度掩码的组合
mask = hueMask&satMask;
}
int main()
{
cv::Mat image = cv::imread("D:\\workplace\\opencv_training\\test3.jpg");
if (!image.data)
return 0;
cv::imshow("Original image", image);
//创建源图像的HSV颜色空间转换
cv::Mat hsv;
cv::cvtColor(image, hsv, CV_BGR2HSV);
// 分割3通道的hsv图像到3个独立矩阵对象
std::vector<cv::Mat> channels;
cv::split(hsv, channels);
// 显示亮度值:即灰度值最高的那个灰度值
cv::imshow("Value", channels[2]);
// 显示饱和度图像
cv::imshow("Saturation", channels[1]);
// 显示色调图像
cv::imshow("Hue", channels[0]);
waitKey();
// image with fixed value固定亮度值通道值全为255
cv::Mat newImage;
cv::Mat tmp(channels[2].clone());
// Value channel will be 255 for all pixels
channels[2] = 255;
// merge back the channels
cv::merge(channels, hsv);
// re-convert to BGR
cv::cvtColor(hsv, newImage, CV_HSV2BGR);
cv::imshow("Fixed Value Image", newImage);
waitKey();
// image with fixed saturation固定饱和度值通道值全为255
channels[1] = 255;
channels[2] = tmp;
cv::merge(channels, hsv);
cv::cvtColor(hsv, newImage, CV_HSV2BGR);
cv::imshow("Fixed saturation", newImage);
waitKey();
// image with fixed value and fixed saturation固定亮度值和饱和度值通道值全为255
channels[1] = 255;
channels[2] = 255;
cv::merge(channels, hsv);
cv::cvtColor(hsv, newImage, CV_HSV2BGR);
cv::imshow("Fixed saturation/value", newImage);
waitKey();
// 进行人脸皮肤的初步检测
image = cv::imread("D:\\workplace\\opencv_training\\test5.png");
if (!image.data)
return 0;
cv::imshow("Original image", image);
waitKey();
// detect skin tone检测肤色
cv::Mat mask;
detectHScolor(image,
160, 10, //这个很重要: hue from 320 degrees to 20 degrees
25, 166, // 这个也很重要:saturation from ~0.1 to 0.65
mask);
// show 使用掩码后的图像
cv::Mat detected(image.size(), CV_8UC3, cv::Scalar(0, 0, 0));
image.copyTo(detected, mask);//mask中值为255的像素点的image灰度值可以拷贝到detected当中
cv::imshow("Detection result", detected);
cv::waitKey();
return 0;
}
opencv学习系列:实例练习(含多个实例)
最新推荐文章于 2024-09-14 12:49:20 发布