opencv之颜色过滤只留下图片中的红色区域
2016-05-23 22:33
288 查看
如图,这次需要在图片中找到卷尺的红色刻度,所以需要对图像做过滤,只留下红色部分。
一开始的想法是分别找到RGB值,然后找到红色区域的部分保留就可以了,不过好像很难确定红色区域的RGB取值范围,所以要把图片转化到HSV空间中去。
在opencv中直接使用cvCvtColor函数就可以啦。
[cpp] view plain copy
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
opencv 的H范围是0~180,红色的H范围大概是(0~8)∪(160,180) ,S是饱和度,一般是大于一个值,S过低就是灰色(参考值S>80),V是亮度,过低就是黑色,过高就是白色(参考值220>V>50)。
所以接下来要做的就是遍历图像,获取图像每个像素点的H,S,V分量,然后做判断,满足条件的就保留,不满足的就赋值为黑色。
我是用opencv中的IplImage来存储图片的。
IplImage获取像素点的方式如下:
[cpp] view plain copy
CvScalar s_hsv = cvGet2D(hsv, j, i);//获取像素点为(i, j)点的HSV的值,i是width值,j是height值
IplImage对像素点赋值的方式如下:
[cpp] view plain copy
CvScalar s;
cvSet2D(hsv, j ,i, s);//对(i,j)处的像素点赋值
分别取得H,S,V分量,注意图像转化的时候BGR2HSV,所以s.val[0]是B或H的值,s.val[1]是G或S的值,s.val[2]则是R或V的值。
因为师弟喜欢用CvMat,所以输入都改成了CvMat,使用的时候inputImage是希望过滤的图片,outputImage则为输出图片,因为outputImage会在函数中进行空间申请与赋值,所以传入参数的时候直接把它设成NULL就可以了。
另外要注意一点,因为是对彩色图像做实验,所以如果传入的图片不是3通道的彩色图片,那么就会出内存错误。
以下打开图片或创建图片的方式都是单通道方式,会出现内存错误。
[cpp] view plain copy
void colorFilter(CvMat *inputImage, CvMat *&outputImage)
{
int i, j;
IplImage* image = cvCreateImage(cvGetSize(inputImage), 8, 3);
cvGetImage(inputImage, image);
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
int width = hsv->width;
int height = hsv->height;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
{
CvScalar s_hsv = cvGet2D(hsv, i, j);//获取像素点为(j, i)点的HSV的值
/*
opencv 的H范围是0~180,红色的H范围大概是(0~8)∪(160,180)
S是饱和度,一般是大于一个值,S过低就是灰色(参考值S>80),
V是亮度,过低就是黑色,过高就是白色(参考值220>V>50)。
*/
CvScalar s;
if (!(((s_hsv.val[0]>0)&&(s_hsv.val[0]<8)) || (s_hsv.val[0]>120)&&(s_hsv.val[0]<180)))
{
s.val[0] =0;
s.val[1]=0;
s.val[2]=0;
cvSet2D(hsv, i ,j, s);
}
}
outputImage = cvCreateMat( hsv->height, hsv->width, CV_8UC3 );
cvConvert(hsv, outputImage);
cvNamedWindow("filter");
cvShowImage("filter", hsv);
waitKey(0);
cvReleaseImage(&hsv);
}
关于函数还有一点要说明,H分量我取得是(0,8),(120,180),S与V分量没有做筛选,如果按照注释部分的进行筛选结果不是很好。
结果如图:
一开始的想法是分别找到RGB值,然后找到红色区域的部分保留就可以了,不过好像很难确定红色区域的RGB取值范围,所以要把图片转化到HSV空间中去。
在opencv中直接使用cvCvtColor函数就可以啦。
[cpp] view plain copy
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
opencv 的H范围是0~180,红色的H范围大概是(0~8)∪(160,180) ,S是饱和度,一般是大于一个值,S过低就是灰色(参考值S>80),V是亮度,过低就是黑色,过高就是白色(参考值220>V>50)。
所以接下来要做的就是遍历图像,获取图像每个像素点的H,S,V分量,然后做判断,满足条件的就保留,不满足的就赋值为黑色。
我是用opencv中的IplImage来存储图片的。
IplImage获取像素点的方式如下:
[cpp] view plain copy
CvScalar s_hsv = cvGet2D(hsv, j, i);//获取像素点为(i, j)点的HSV的值,i是width值,j是height值
IplImage对像素点赋值的方式如下:
[cpp] view plain copy
CvScalar s;
cvSet2D(hsv, j ,i, s);//对(i,j)处的像素点赋值
分别取得H,S,V分量,注意图像转化的时候BGR2HSV,所以s.val[0]是B或H的值,s.val[1]是G或S的值,s.val[2]则是R或V的值。
因为师弟喜欢用CvMat,所以输入都改成了CvMat,使用的时候inputImage是希望过滤的图片,outputImage则为输出图片,因为outputImage会在函数中进行空间申请与赋值,所以传入参数的时候直接把它设成NULL就可以了。
另外要注意一点,因为是对彩色图像做实验,所以如果传入的图片不是3通道的彩色图片,那么就会出内存错误。
以下打开图片或创建图片的方式都是单通道方式,会出现内存错误。
IplImage *input = cvLoadImage(path, 0),
CvMat* M = cvCreateMat(4,4,CV_32FC1); //或是8UC1, 因为C1表示nChannel = 1,也就是单通道
[cpp] view plain copy
void colorFilter(CvMat *inputImage, CvMat *&outputImage)
{
int i, j;
IplImage* image = cvCreateImage(cvGetSize(inputImage), 8, 3);
cvGetImage(inputImage, image);
IplImage* hsv = cvCreateImage( cvGetSize(image), 8, 3 );
cvCvtColor(image,hsv,CV_BGR2HSV);
int width = hsv->width;
int height = hsv->height;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
{
CvScalar s_hsv = cvGet2D(hsv, i, j);//获取像素点为(j, i)点的HSV的值
/*
opencv 的H范围是0~180,红色的H范围大概是(0~8)∪(160,180)
S是饱和度,一般是大于一个值,S过低就是灰色(参考值S>80),
V是亮度,过低就是黑色,过高就是白色(参考值220>V>50)。
*/
CvScalar s;
if (!(((s_hsv.val[0]>0)&&(s_hsv.val[0]<8)) || (s_hsv.val[0]>120)&&(s_hsv.val[0]<180)))
{
s.val[0] =0;
s.val[1]=0;
s.val[2]=0;
cvSet2D(hsv, i ,j, s);
}
}
outputImage = cvCreateMat( hsv->height, hsv->width, CV_8UC3 );
cvConvert(hsv, outputImage);
cvNamedWindow("filter");
cvShowImage("filter", hsv);
waitKey(0);
cvReleaseImage(&hsv);
}
关于函数还有一点要说明,H分量我取得是(0,8),(120,180),S与V分量没有做筛选,如果按照注释部分的进行筛选结果不是很好。
结果如图:
相关文章推荐
- Nginx反向代理的配置
- Learning OpenCV: read AVI video file
- linux命令之tail
- Android 基础总结:(一)Android系统架构
- RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较
- Linux 添加开机自启动
- linux命令之rpm
- bash扩展
- linux基本命令(30)——chown命令
- CentOS6.6图文详细安装教程(有些设置大部分教程没出现过,附带网络设置等)
- centos6.5 搭建hadoop 开发环境(单台服务器)
- [Linux][Install guide]Ubuntu多系统安装注意事项
- Linux I/O模型 与 Java I/O模型、驱动中的异步函数 的区别。
- linux实践——内核编程 基础模块
- kalilinux安装lantern
- 【BZOJ4199】品酒大会,后缀数组+并查集维护
- 高并发金融应用架构优化与平台创新
- shell通配符
- 阿里云服务器-百度开放云域名-WordPress网站部署踩的坑
- kalilinux 更新