目前章节
1.从零开始安卓端相机功能开发(一)了解用什么去开发以及流程
2.从零开始安卓端相机功能开发(二)让我们来开发一个相机
3.从零开始开发Android相机app(三)简单介绍图像滤镜功能
源码地址:https://github.com/307572384/GPItest/commit/a89a605cec14bd573cd90994c973cfdd00f97991?diff=unified
滤镜;主要是用来实现图像的各种特殊效果。它在Photoshop中具有非常神奇的作用。所有的滤镜在Photoshop中都按分类放置在菜单中,使用时只需要从该菜单中执行这命令即可。滤镜的操作是非常简单的,但是真正用起来却很难恰到好处。滤镜通常需要同通道、图层等联合使用,才能取得最佳艺术效果。如果想在最适当的时候应用滤镜到最适当的位置,除了平常的美术功底之外,还需要用户对滤镜的熟悉和操控能力,甚至需要具有很丰富的想象力。这样,才能有的放矢的应用滤镜,发挥出艺术才华。
以上来源于百度百科,当然我们的Android相机开发的图像滤镜也不是那么简单的需要自己有一些动手能力和一定的英语阅读水平和数学能力才能够熟悉的一些东西,这里我个人建议要想变得更强英语和数学这两个要变得非常强才可以,毕竟有些外国文章写得非常不错可以用来参考,但是翻译却很少所以得提高自己的能力才行。这个是我这几天的学习感受。
首先我们写滤镜效果可以使用现成的如GPUImage或者是其他的现成付费SDK也可以自己写当然这种的话就比较麻烦涉及到算法之类的,我个人比较推荐GPUImage这一款开源项目。
GPUImage 是iOS下一个开源的基于GPU的图像处理库,提供各种各样的图像处理滤镜,并且支持照相机和摄像机的实时滤镜。GPUImage for Android是它在Android下的实现,同样也是开源的。其中提供了几十多种常见的图片滤镜API,且其机制是基于GPU渲染,处理速度相应也比较快,是一个不错的图片实时处理框架。
而且现在还在更新状态中。
需要的可以去看看GPUImageGithub开源项目
滤镜处理对象:通常分为两类:1.静态图片;2.实时相机预览;3.视频添加滤镜;
实现方式有多种,比如通过调用Android系统提供的图像处理API,可以设置图片的色调、饱和度、亮度,也可以调用ColorMatrix进行更加精确的图片色彩调控,还可以使用更加精细化的像素处理方式—提取图片像素点,然后对每个像素点进行处理,使图片变换不同的色彩效果,以上的方式都是调用Android系统提供的API进行处理,难点在于图像处理算法的研究,这也是专业图像处理人员的工作之一,尝试不同色彩矩阵的配合,可以创建出不同的色彩效果。
GPUImage是iOS的一个开源库,后来也有了Android的版本,可以实现五十多种的滤镜效果,不用开发者自己进行滤镜算法的实现,处理起来更加的方便,而且GPUImage可以做到的不仅仅是像ColorMatrix一样的色彩特效,还可以进一步实现美颜相机需要的其他特效,比如磨皮,美白等,功能会更加强大。
环境搭建
首先,要使用这个库自然是要先导入依赖,在app的gradle文件中添加:
repositories {
google()
jcenter()
}
dependencies {
compile 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1'
}
至于怎么创建Assets文件我们就使用这个
Android图像滤镜框架GPUImage从配置到应用
然后里面的素材图片大家可以随便写一个然后导入进去。
GPUImage主要通过一个GPUImageFilter类来提供各种滤镜效果实现类,比如我们来实现一个将图片变成的鱼眼的滤镜:
“GPUImageBulgeDistortionFilter” 【凸起失真,鱼眼效果】这个是我们需要实现的效果。
我们来看一下鱼眼效果
这里是静态滤镜的MainActivity里面有滤镜的主要功能:包括滤镜显示到屏幕上和拖拉调整图片饱和度的功能
务必在AndroidManifest中先添加联网权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.Image;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.SeekBar;
import junit.framework.Assert;
import java.io.IOException;
import java.io.InputStream;
import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.GPUImageBulgeDistortionFilter;
import jp.co.cyberagent.android.gpuimage.GPUImageGrayscaleFilter;
import jp.co.cyberagent.android.gpuimage.GPUImageSaturationFilter;
public class MainActivity extends AppCompatActivity {
private GPUImage gpuImage;
//显示处理结果
private ImageView resultIv;
//进度条
private SeekBar seekBar;
private Button bt_net;//点击跳转到图片网络滤镜转换
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
resultIv = (ImageView)findViewById(R.id.resultIv);
bt_net=(Button)findViewById(R.id.button) ;
seekBar = (SeekBar)this.findViewById(R.id.seekbar);
seekBar.setMax(10);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//通过进度条的值更改饱和度
resultIv.setImageBitmap(getGPUImageFromAssets(progress));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
//初始化图片
resultIv.setImageBitmap(getGPUImageFromAssets(0));
bt_net.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,NetActivity.class);
startActivity(intent);
}
});
}
//根据传进来的数值设置素材饱和度
public Bitmap getGPUImageFromAssets(int progress)
{
//获得Assets资源文件
AssetManager as = getAssets();
InputStream is = null;
Bitmap bitmap = null;
try{
is = as.open("link.jpg");
bitmap = BitmapFactory.decodeStream(is);
is.close();
}catch (IOException e)
{
Log.e("GPUImage","Error");
}
gpuImage = new GPUImage(this);
gpuImage.setImage(bitmap);
gpuImage.setFilter(new GPUImageBulgeDistortionFilter());
bitmap = gpuImage.getBitmapWithFilterApplied();
//显示处理图片后的照片
return bitmap;
}
}
PS:这里注意一下有些滤镜功能是没有饱和度如鱼眼功能
这里是MainActivity的activity_layout布局文件
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.beta.gpitest.MainActivity">
<ImageView
android:id="@+id/resultIv"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="23dp"
android:layout_marginTop="10dp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="93dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:text="跳转到网络图片滤镜效果"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/resultIv" />
<Button
android:id="@+id/setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:text="setting"
app:layout_constraintBaseline_toBaselineOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent" />
</android.support.constraint.ConstraintLayout>
如果我们需要联网进行滤镜效果的话,由于访问网络图片,所以需要放在子线程中进行,所以这里通过AsynTask(Android异步线程,不清楚的可以看下这篇文章AsynTask使用简介),现在子线程请求完网络图片并转换为Bitmap传递给主线程中对图片进行滤镜处理并显示出来。
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import jp.co.cyberagent.android.gpuimage.GPUImage;
import jp.co.cyberagent.android.gpuimage.GPUImageGrayscaleFilter;
public class NetActivity extends AppCompatActivity {
private GPUImage gpuImage;
//显示处理结果
private ImageView resultIv;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.net_main);
resultIv = (ImageView) findViewById(R.id.imagex);
//开启异步线程加载图片并处理
MyAsynTask asynTask = new MyAsynTask();
asynTask.execute();
}
class MyAsynTask extends AsyncTask<Integer,Integer,Bitmap>{
@Override
protected Bitmap doInBackground(Integer... params) {
//写入图片的url
Bitmap bitmap = getGPUImageFromURL("https://img-blog.csdn.net/20180422104130848?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTEwMTE3Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70");
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
// 使用GPUImage处理图像
gpuImage = new GPUImage(getApplicationContext());
gpuImage.setImage(bitmap);
gpuImage.setFilter(new GPUImageGrayscaleFilter());
bitmap = gpuImage.getBitmapWithFilterApplied();
//显示处理后的图片存储到bitmap
resultIv.setImageBitmap(bitmap);
}
}
public static Bitmap getGPUImageFromURL(String url) {
Bitmap bitmap = null;
try {
URL iconUrl = new URL(url);
URLConnection conn = iconUrl.openConnection();
HttpURLConnection http = (HttpURLConnection) conn;
int length = http.getContentLength();
conn.connect();
// 获得图像的字符流
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is, length);
bitmap = BitmapFactory.decodeStream(bis);
bis.close();
is.close();// 关闭流
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
}
网络图片的layout这个很简单就只是一个imageview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imagex"
android:layout_width="match_parent"
android:layout_height="229dp"
android:layout_gravity="center_horizontal" />
</LinearLayout>
这个静态滤镜和联网滤镜功能已经实现了,接下来我需要做的是实现人脸识别美颜+组合滤镜功能,不知道大家有没有学习过或者使用过lightroom这款滤镜调整的WIN平台下的软件因为我本身副职业是走的是摄影这条路所以有所学习到,但是我认为GpuImage的滤镜功能就我暂时学到的可能有点少所以想要实现像LightRoom的那些大片滤镜功能就稍微有些复杂不过还是慢慢的一步一步走下去比较好一点。
下面我们来看看我们走到哪一步了。
Coloradjustments: 31 filters, 颜色处理相关
#import "GPUImageBrightnessFilter.h" //亮度
#import "GPUImageExposureFilter.h" //曝光
#import "GPUImageContrastFilter.h" //对比度
#import "GPUImageSaturationFilter.h" //饱和度
#import "GPUImageGammaFilter.h" //伽马线
#import "GPUImageColorInvertFilter.h" //反色
#import "GPUImageSepiaFilter.h" //褐色(怀旧)
#import "GPUImageLevelsFilter.h" //色阶
#import "GPUImageGrayscaleFilter.h" //灰度
#import "GPUImageHistogramFilter.h" //色彩直方图,显示在图片上
#import "GPUImageHistogramGenerator.h" //色彩直方图
#import "GPUImageRGBFilter.h" //RGB
#import "GPUImageToneCurveFilter.h" //色调曲线
#import "GPUImageMonochromeFilter.h" //单色
#import "GPUImageOpacityFilter.h" //不透明度
#import "GPUImageHighlightShadowFilter.h" //提亮阴影
#import "GPUImageFalseColorFilter.h" //色彩替换(替换亮部和暗部色彩)
#import "GPUImageHueFilter.h" //色度
#import "GPUImageChromaKeyFilter.h" //色度键
#import "GPUImageWhiteBalanceFilter.h" //白平横
#import "GPUImageAverageColor.h" //像素平均色值
#import "GPUImageSolidColorGenerator.h" //纯色
#import "GPUImageLuminosity.h" //亮度平均
#import "GPUImageAverageLuminanceThresholdFilter.h" //像素色值亮度平均,图像黑白(有类似漫画效果)
#import "GPUImageLookupFilter.h" //lookup 色彩调整
#import "GPUImageAmatorkaFilter.h" //Amatorka lookup
#import "GPUImageMissEtikateFilter.h" //MissEtikate lookup
#import "GPUImageSoftEleganceFilter.h" //SoftElegance lookup
**#pragma mark - 图像处理 Handle Image**
Image processing: 40 filters, 图像处理相关.
#import "GPUImageCrosshairGenerator.h" //十字
#import "GPUImageLineGenerator.h" //线条
#import "GPUImageTransformFilter.h" //形状变化
#import "GPUImageCropFilter.h" //剪裁
#import "GPUImageSharpenFilter.h" //锐化
#import "GPUImageUnsharpMaskFilter.h" //反遮罩锐化
//#import "GPUImageFastBlurFilter.h" //模糊
#import "GPUImageGaussianBlurFilter.h" //高斯模糊
#import "GPUImageGaussianSelectiveBlurFilter.h" //高斯模糊,选择部分清晰
#import "GPUImageBoxBlurFilter.h" //盒状模糊
#import "GPUImageTiltShiftFilter.h" //条纹模糊,中间清晰,上下两端模糊
#import "GPUImageMedianFilter.h" //中间值,有种稍微模糊边缘的效果
#import "GPUImageBilateralFilter.h" //双边模糊
#import "GPUImageErosionFilter.h" //侵蚀边缘模糊,变黑白
#import "GPUImageRGBErosionFilter.h" //RGB侵蚀边缘模糊,有色彩
#import "GPUImageDilationFilter.h" //扩展边缘模糊,变黑白
#import "GPUImageRGBDilationFilter.h" //RGB扩展边缘模糊,有色彩
#import "GPUImageOpeningFilter.h" //黑白色调模糊
#import "GPUImageRGBOpeningFilter.h" //彩色模糊
#import "GPUImageClosingFilter.h" //黑白色调模糊,暗色会被提亮
#import "GPUImageRGBClosingFilter.h" //彩色模糊,暗色会被提亮
#import "GPUImageLanczosResamplingFilter.h" //Lanczos重取样,模糊效果
#import "GPUImageNonMaximumSuppressionFilter.h" //非最大抑制,只显示亮度最高的像素,其他为黑
#import "GPUImageThresholdedNonMaximumSuppressionFilter.h" //与上相比,像素丢失更多
#import "GPUImageSobelEdgeDetectionFilter.h" //Sobel边缘检测算法(白边,黑内容,有点漫画的反色效果)
#import "GPUImageCannyEdgeDetectionFilter.h" //Canny边缘检测算法(比上更强烈的黑白对比度)
#import "GPUImageThresholdEdgeDetectionFilter.h" //阈值边缘检测(效果与上差别不大)
#import "GPUImagePrewittEdgeDetectionFilter.h" //普瑞维特(Prewitt)边缘检测(效果与Sobel差不多,貌似更平滑)
#import "GPUImageXYDerivativeFilter.h" //XYDerivative边缘检测,画面以蓝色为主,绿色为边缘,带彩色
#import "GPUImageHarrisCornerDetectionFilter.h" //Harris角点检测,会有绿色小十字显示在图片角点处
#import "GPUImageNobleCornerDetectionFilter.h" //Noble角点检测,检测点更多
#import "GPUImageShiTomasiFeatureDetectionFilter.h" //ShiTomasi角点检测,与上差别不大
#import "GPUImageMotionDetector.h" //动作检测
#import "GPUImageHoughTransformLineDetector.h" //线条检测
#import "GPUImageParallelCoordinateLineTransformFilter.h" //平行线检测
#import "GPUImageLocalBinaryPatternFilter.h" //图像黑白化,并有大量噪点
#import "GPUImageLowPassFilter.h" //用于图像加亮
#import "GPUImageHighPassFilter.h" //图像低于某值时显示为黑
#pragma mark - 视觉效果 Visual Effect
Visual effects: 25 filters, 视觉效果相关
#import "GPUImageSketchFilter.h" //素描
#import "GPUImageThresholdSketchFilter.h" //阀值素描,形成有噪点的素描
#import "GPUImageToonFilter.h" //卡通效果(黑色粗线描边)
#import "GPUImageSmoothToonFilter.h" //相比上面的效果更细腻,上面是粗旷的画风
#import "GPUImageKuwaharaFilter.h" //桑原(Kuwahara)滤波,水粉画的模糊效果;处理时间比较长,慎用
#import "GPUImageMosaicFilter.h" //黑白马赛克
#import "GPUImagePixellateFilter.h" //像素化
#import "GPUImagePolarPixellateFilter.h" //同心圆像素化
#import "GPUImageCrosshatchFilter.h" //交叉线阴影,形成黑白网状画面
#import "GPUImageColorPackingFilter.h" //色彩丢失,模糊(类似监控摄像效果)
#import "GPUImageVignetteFilter.h" //晕影,形成黑色圆形边缘,突出中间图像的效果
#import "GPUImageSwirlFilter.h" //漩涡,中间形成卷曲的画面
#import "GPUImageBulgeDistortionFilter.h" //凸起失真,鱼眼效果
#import "GPUImagePinchDistortionFilter.h" //收缩失真,凹面镜
#import "GPUImageStretchDistortionFilter.h" //伸展失真,哈哈镜
#import "GPUImageGlassSphereFilter.h" //水晶球效果
#import "GPUImageSphereRefractionFilter.h" //球形折射,图形倒立
#import "GPUImagePosterizeFilter.h" //色调分离,形成噪点效果
#import "GPUImageCGAColorspaceFilter.h" //CGA色彩滤镜,形成黑、浅蓝、紫色块的画面
#import "GPUImagePerlinNoiseFilter.h" //柏林噪点,花边噪点
#import "GPUImage3x3ConvolutionFilter.h" //3x3卷积,高亮大色块变黑,加亮边缘、线条等
#import "GPUImageEmbossFilter.h" //浮雕效果,带有点3d的感觉
#import "GPUImagePolkaDotFilter.h" //像素圆点花样
#import "GPUImageHalftoneFilter.h" //点染,图像黑白化,由黑点构成原图的大致图形
#pragma mark - 混合模式 Blend
Blending modes: 29 filters, 混合模式相关.
#import "GPUImageMultiplyBlendFilter.h" //通常用于创建阴影和深度效果
#import "GPUImageNormalBlendFilter.h" //正常
#import "GPUImageAlphaBlendFilter.h" //透明混合,通常用于在背景上应用前景的透明度
#import "GPUImageDissolveBlendFilter.h" //溶解
#import "GPUImageOverlayBlendFilter.h" //叠加,通常用于创建阴影效果
#import "GPUImageDarkenBlendFilter.h" //加深混合,通常用于重叠类型
#import "GPUImageLightenBlendFilter.h" //减淡混合,通常用于重叠类型
#import "GPUImageSourceOverBlendFilter.h" //源混合
#import "GPUImageColorBurnBlendFilter.h" //色彩加深混合
#import "GPUImageColorDodgeBlendFilter.h" //色彩减淡混合
#import "GPUImageScreenBlendFilter.h" //屏幕包裹,通常用于创建亮点和镜头眩光
#import "GPUImageExclusionBlendFilter.h" //排除混合
#import "GPUImageDifferenceBlendFilter.h" //差异混合,通常用于创建更多变动的颜色
#import "GPUImageSubtractBlendFilter.h" //差值混合,通常用于创建两个图像之间的动画变暗模糊效果
#import "GPUImageHardLightBlendFilter.h" //强光混合,通常用于创建阴影效果
#import "GPUImageSoftLightBlendFilter.h" //柔光混合
#import "GPUImageChromaKeyBlendFilter.h" //色度键混合
#import "GPUImageMaskFilter.h" //遮罩混合
#import "GPUImageHazeFilter.h" //朦胧加暗
#import "GPUImageLuminanceThresholdFilter.h" //亮度阈
#import "GPUImageAdaptiveThresholdFilter.h" //自适应阈值
#import "GPUImageAddBlendFilter.h" //通常用于创建两个图像之间的动画变亮模糊效果
#import "GPUImageDivideBlendFilter.h" //通常用于创建两个图像之间的动画变暗模糊效果
本文参考自:
Android图像滤镜框架GPUImage从配置到应用
Android使用GPUImage实现滤镜效果精炼详解(一)