opencv之颜色过滤只留下图片中的红色区域操作
作者:jianjian1992 发布时间:2021-04-03 19:15:28
如图,这次需要在图片中找到卷尺的红色刻度,所以需要对图像做过滤,只留下红色部分。
一开始的想法是分别找到RGB值,然后找到红色区域的部分保留就可以了,不过好像很难确定红色区域的RGB取值范围,所以要把图片转化到HSV空间中去。
在opencv中直接使用cvCvtColor函数就可以啦。
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获取像素点的方式如下:
CvScalar s_hsv = cvGet2D(hsv, j, i);//获取像素点为(i, j)点的HSV的值,i是width值,j是height值
IplImage对像素点赋值的方式如下:
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,也就是单通道
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分量没有做筛选,如果按照注释部分的进行筛选结果不是很好。
结果如图:
补充知识:opencv实现图像去除单一颜色背景
思路
因为背景是固定颜色,很容易筛选出背景,然后将其设为白色完全透明即可。
代码
#coding=utf-8
import cv2 as cv
bg_color = [197, 102, 6]
threshold = 3000
def calc_diff(pixel):
'''
计算pixel与背景的离差平方和,作为当前像素点与背景相似程度的度量
'''
return (pixel[0]-bg_color[0])**2 + (pixel[1]-bg_color[1])**2 + (pixel[2]-bg_color[2])**2
def remove_bg():
image_path = './logo.png'
logo = cv.imread(image_path)
logo = cv.cvtColor(logo, cv.COLOR_BGR2BGRA) #将图像转成带透明通道的BGRA格式
h, w = logo.shape[0:2]
for i in range(h):
for j in range(w):
if calc_diff(logo[i][j]) < threshold:
#若果logo[i][j]为背景,将其颜色设为白色,且完全透明
logo[i][j][0] = 255
logo[i][j][1] = 255
logo[i][j][2] = 255
logo[i][j][3] = 0
cv.imwrite("./logo_rmbg.png", logo)
if __name__ == '__main__':
remove_bg()
使用方法
修改第5行的bg_color为图片背景的bgr值,以及第6行的threshold(threshold越大,覆盖的像素越多)。
效果:
emmm,事实证明背景附近的颜色不是严格的背景色,后来将字填充后好多了。
来源:https://blog.csdn.net/jianjian1992/article/details/45027993


猜你喜欢
- 本文实例讲述了Python3爬虫学习之MySQL数据库存储爬取的信息。分享给大家供大家参考,具体如下:数据库存储爬取的信息(MySQL)爬取
- 目录一、生产环境,开发环境切换第一种方法:通过配置.env文件来实现第二种方法二、过滤器三、moment时间库使用一、生产环境,开发环境切换
- 如下所示:>> type(np.newaxis)NoneType>> np.newaxis == NoneTruen
- 本文实例为大家分享了python处理大日志文件的具体代码,供大家参考,具体内容如下# coding=utf-8import sysimpor
- 前言你知道a**3是什么意思吗?你知道怎么打印模块路径吗?你知道reduce()函数怎么用和列表怎么拼接字符串吗?然而你可能全都知道但是还是
- 看代码吧~import torchprint(torch.__version__)补充:pytorch不同版本安装以及版本查看一:基于con
- yaml简单介绍YAML是一种标记语言,它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、
- 基本概念数字图像定义对于一幅图像,我们可以将其放入坐标系中,这里取图像左上定点为坐标原点,x 轴向右,和笛卡尔坐标系x轴相同;y 轴向下,和
- 引言所谓 路由 就是根据不同的 url 地址展示不同的内容或页面形象点 举个栗子??:电话的拨号界面咱们都见过都使用过你输入一串号码,就可以
- 前言electron+vuecli3 实现设置打印机,静默打印小票功能网上相关的资料比较少,这里给大家分享一下,希望大家可以少踩一些坑git
- 现在有一个横向的IFRAME,需要通过点击iframe外的一个图片来横向滚动iframe内的一个html页,但又不想让看见iframe的滚动
- 1、前言在Python中元组是一个和列表非常类似的数据类型,不同之处就是列表中的元素可以修改,而元组之中的元素不可以修改。2、定义和使用元组
- 一个post类型的接口怎么编写脚本实现1、打开网页,在fiddler上获取到接口的URL2、用Python的requests库实现impor
- 以下内容都是针对Pytorch 1.0-1.1介绍。很多文章都是从Dataset等对象自下往上进行介绍,但是对于初学者而言,其实这并不好理解
- pandas中对DataFrame筛选数据的方法有很多的,以后会后续进行补充,这里只整理遇到错误的情况。1.使用布尔型DataFrame对数
- SQL 中的运算符 1算术运算符:+:加运算,求两个数或表达式想加的和-:减运算,求两个数或表达式相减的差*,乘运算,求两个数或表
- floor()方法返回不大于x的最大整数(向下取整)。语法以下是floor()方法的语法:import mathmath.flo
- 手写数字识别算法的设计与实现本文使用python基于TensorFlow设计手写数字识别算法,并编程实现GUI界面,构建手写数字识别系统。这
- 第一类工厂相当于mootools的Native方法,用于创建一些具有扩展能力的类,但这些类并没有继承能力,此类工厂也不能以某个类作为蓝本创建
- 本文先了解一个简单阈值函数,以了解一个阈值算法的具体参数。 然后比较不同阈值函数的区别。同样的,先用一副图说明本文重要大纲: #! usr/