基于opencv的支持多格式的滤镜算法代码实现

1. 定义一个结构体保存一些算法处理需要的图片信息:

struct m_picData {
 int width;
 int heigh;
 int picType;
};

2. 定义一个滤镜基类:

class Filter{
  struct m_picData picData;
}

需要有一个实际处理数据的函数,接收输入、输出buffer两个参数。
此处需要利用多态,所以将函数定义为虚函数。

virtual void doFilter(uchar* inputbuf, uchar* outputbuf) = 0;

3. 定义反相滤镜算法类,继承滤镜基类:

class InverseFilter : Filter {
 struct m_picData picData;
 void doFilter(uchar* inputbuf, uchar* outputbuf);
}

4. 实现反相滤镜类:

(1)在构造函数中填充picData:

InverseFilter::InverseFilter(struct m_picData pd)
{
  picData.width = pd.width;
  picData.heigh = pd.heigh;
  picData.picType = pd.picType;
}

(2)根据picType不同,需要对应不同的处理方法,所以增加两个方法用于实际实现数据处理:

 void doJPGFilter(uchar* inputbuf, uchar* outputbuf);
 void doYuvFilter(uchar* inputbuf, uchar* outputbuf);

(3)在doFilter中调用对应接口:

void InverseFilter::doFilter(uchar* inputbuf, uchar* outputbuf) {
  switch (picData.picType) {
  case JPG:
    doJPGFilter(inputbuf, outputbuf);
    break;
  case YUV_NV12:
    doYuvFilter(inputbuf, outputbuf);
    break;
  }
}

5. 反相算法的数据处理

(1)JPG:
R G B各占8bit,取的每像素的R值,使用(255 - R)替换R值,G B做同样处理,即可获得反相效果。
每行每像素遍历处理:

void InverseFilter::doJPGFilter(uchar* inputbuf, uchar* outputbuf)
{
	for (int y = 0; y < picData.heigh; y++)
	{
		uchar* P0 = inputbuf + (y * picData.width * 3);
		uchar* P1 = outputbuf + (y * picData.width * 3);
		for (int x = 0; x < picData.width; x++)
		{
			P1[3 * x] = 255 - P0[3 * x];
			P1[3 * x + 1] = 255 - P0[3 * x + 1];
			P1[3 * x + 2] = 255 - P0[3 * x + 2];
		}
	}
}

(2)NV12:
(a.) 已知: Y = 0.3R + 0.59G + 0.11B
U = 0.493(B - Y)
V = 0.877(R - Y)
(b.) 计算反相值:
反相Y = 0.3(255 - R) + 0.59(255 - G) + 0.11(255 - B)
= 255 - (0.3R + 0.59G + 0.11B)
= 255 -Y
反相U = 0.493((255 - B) - (255 - Y))
= -U
反相V = 0.877((255 - R) - (255 - Y))
= -V
(c.) Y U V取值:
NV12是YUV420的格式,四个Y共用一组UV。所以以四个Y一组UV为一个单元做处理。每个单元格式如下:

Y    Y
  UV  
Y    Y

代码实现:

void InverseFilter::doYuvFilter(uchar* inputbuf, uchar* outputbuf)
{
	for (int y = 0; y < picData.heigh; y += 2) {
		for (int x = 0; x < picData.width; x += 2) {
			outputbuf[y * picData.width + x] = 255 - inputbuf[y * picData.width + x];
			outputbuf[y * picData.width + (x + 1)] = 255 - inputbuf[y * picData.width + (x + 1)];
			outputbuf[(y + 1) * picData.width + x] = 255 - inputbuf[(y + 1) * picData.width + x];
			outputbuf[(y + 1) * picData.width + (x + 1)] = 255 - inputbuf[(y + 1) * picData.width + (x + 1)];
			outputbuf[(y / 2 + picData.heigh) * picData.width + x] = -inputbuf[(y / 2 + picData.heigh) * picData.width + x];
			outputbuf[(y / 2 + picData.heigh) * picData.width + (x + 1)] = -inputbuf[(y / 2 + picData.heigh) * picData.width + (x + 1)];
		}
	}
}

6. 使用一个工厂管理不同类型的滤镜:

Filter* FilterFactory::createFilter(int filterType, struct m_picData pd)
{
	Filter* filter = NULL;
	switch (filterType) {
	case INVERSEFILTER:
		filter = new InverseFilter(pd);
		break;
	case VINTAGEFILTER:
		filter = new VintageFilter(pd);
		break;
	}
	return filter;
}

7. 滤镜使用:

(1)填充待处理图像的相关属性:

 struct m_picData picData;
 picData.width = image.cols;
 picData.heigh = image.rows;
 picData.picType = JPG;

(2)创建滤镜对象:

Filter* filter = FilterFactory::createFilter(INVERSEFILTER, picData);

(3)调用处理方法:

filter->doFilter(image.data , img.data);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值