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);