Android OpenCV添加图像效果

来源:互联网 发布:单片机与微机的区别 编辑:程序博客网 时间:2024/04/28 17:15
    本文重点介绍OpenCV获取到的帧图像处理,关于OpenCV中获取打开相机,及相机缓冲帧的方法请参考
Android OpenCV获取相机并拍(Android Studio)。
    首先我们需要从相机缓冲帧中获取到RGBA矩阵:
Mat rgba = inputFrame.rgba();
    处理像素的方法采用Filter接口的方式,Filter接口代码如下:
public interface Filter {
public abstract void apply(Mat src, Mat dst);
}
    接口中定义了apply方法,接收一个原始数据的Mat对象,和一个结果数据的Mat对象。紧接着,定义一个NoneFilter:
public class NoneFilter implements Filter {

@Override
public void apply(Mat src, Mat dst) {
// Do nothing.
}
}
    NoneFilter类的apply()方法什么也没做,这个Filter的功能就是不对数据做任何处理。

接下来看我们具体的添加图像效果的Filter
1.混合颜色通道:
1.RecolorRCFilter:
public class RecolorRCFilter implements Filter {

private ArrayList<Mat> mChannels = new ArrayList<Mat>(4);

@Override
public void apply(Mat src, Mat dst) {
Core.split(src, mChannels);

Mat g = mChannels.get(1);
Mat b = mChannels.get(2);

// dst.g = 0.5 * src.g + 0.5 * src.b
Core.addWeighted(g, 0.5, b, 0.5, 0.0, g);

// dst.b = dst.g
mChannels.set(2, g);

Core.merge(mChannels, dst);
}
}
       该滤镜将绿色和蓝色转换为青色,并保留有限的红色和青色调色板。该滤镜可模拟早期电影和计算机游戏显示效果。该滤镜主要方法介绍:
       Core.split(Mat m, List<Mat> mv)方法负责分离通道,该方法对应的参数为源矩阵和目标矩阵列表。来自原矩阵的各个通道被复制至目标列表中的独立通道的矩阵中。

       Core.addWeight(Mat src1, double alpha, Mat src2, double beta, double gramma, Mat dst)方法可用于计算两个通道的加权平均值。前4个参数分别表示为权值和源矩阵;第5个参数表示常数,并加入到计算结果中;最后一个参数为目标矩阵。

       Core.merge(List<Mat> mv, Mat m)方法可视为Core.split方法的逆制方法,可将独立通道重新生成多通道图像。

2、RecolorRGVFilter:
      该Filter与RecolorRCFilter基本相同,只是将addWeighted操作换成了min操作,不同处的代码为:
Core.min(b, r, b);
Core.min(b, g, b);
       Core.min(Mat src1, Mat src2, Mat dst)方法接收一组源矩阵和目标矩阵,执行逐个元素的min操作,min操作可以降低输出通道的饱和度。
       该滤镜将降低蓝色的饱和度,并遗留有限的红色、绿色、和白色调色板。该滤镜模拟了早期电影和计算机游戏的显示效果。
3、RecolorRMVFilter:
 该Filter与RecolorRCFilter基本相同,只是将addWeighted操作换成了max操作,不同处的代码为:
Core.max(b, r, b);
Core.max(b, g, b);
       Core.max(Mat src1, Mat src2, Mat dst)接收一组源矩阵和目标矩阵,执行逐个元素的max操作。max操作可以降低输出通道互补色的饱和度。
        该滤镜将降低黄色的饱和度,并遗留有限的青色、洋红、和白色调色板。该滤镜模拟了20世纪80年代计算机游戏的效果。

2.使用卷积过滤处理邻接像素
        在卷积滤镜中,各个输出像素的通道值为邻接输入像素对应通道值得加权平均的结果。二话不说,先上代码:
public class StrokeEdgesFilter implements Filter {

private Mat mKernel = new MatOfInt(
0, 0, 1, 0, 0,
0, 1, 2, 1, 0,
1, 2, -16, 2, 1,
0, 1, 2, 1, 0,
0, 0, 1, 0, 0
);
private Mat mEdges = new Mat();

@Override
public void apply(Mat src, Mat dst) {
Imgproc.filter2D(src, mEdges, -1, mKernel);
Core.bitwise_not(mEdges, mEdges);
Core.multiply(src, mEdges, dst, 1.0 / 255.0);
}
}
Core.filter2D(Mat src, Mat dst, int depth, double delta)方法可以自定义卷积矩阵,depth参数可以为下面内容之一:
  1.   -1:与数据源具有相同的类型;
  2.  CvType.CV_16S:16位有符号整数
  3.  CvType.CV_32F:32位浮点数
  4.  CvType.CV_64S:64位浮点数

Core.bitwise_not(Mat src, Mat dst):方法逆置图像的亮度和颜色,即白色变为黑色,红色变为青色等。

Core.multipy(Mat src1, Mat src2, Mat dst, double scale):该方法通过在对应数据值之间执行乘法运算,进而混合一组图像。最终结果可以通过scale参数进行缩放计算。
       通过该滤镜实现了黑色边框效果。卷积滤镜还可以实现腐蚀、羽化等多种效果,这些效果将在后续文章中介绍。

        最后在CameraActivity的的onCameraFrame方法中添加滤镜处理代码:
@Override
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat rgba = inputFrame.rgba();

// Apply the active filters.
mCurveFilters[mCurveFilterIndex].apply(rgba, rgba);
mMixerFilters[mMixerFilterIndex].apply(rgba, rgba);
mConvolutionFilters[mConvolutionFilterIndex].apply(rgba, rgba);
return rgba;
}
       本实例中,点击ActionBar的代码可实现滤镜的切换,获得不同的图片效果,运行效果如图所以:


项目Github地址:https://github.com/BruceT2010/OpenCV4AndroidSecondSight
0 0
原创粉丝点击