颜色矩阵 滤镜 ColorMatrix


颜色矩阵原理
 
    
 
    
色彩的三要素
1、色相。色相通俗的说就是“颜色”,色相的改变就是颜色的改变,色相的调节伴随着红橙黄绿蓝紫的变化。
2、亮度。明度通俗的说就是“光照度”,明度的改变就是光照在物体上带来的改变,明度的调节伴随着越高,光越强,越泛白(就像过曝一样,往白色上偏离);越低,光越弱,越往黑里偏
3、饱和度。饱和度通俗的说就是“色彩的纯度”,饱和度的改变会影响颜色的鲜艳程度,以红色为例子,越高,越接近红色,越低则越接近灰色(黑白)

在编程中有时候需要对图片做特殊的处理,比如将图片做出黑白的,或者老照片的效果,有时候还要对图片进行变换,以拉伸,扭曲等等。 这些效果在android中有很好的支持,通过颜色矩阵 ColorMatrix 和坐标变换矩阵 Matrix 可以完美的做出上面的所说的效果。
android中可以通过颜色矩阵 ColorMatrix 方便的操作颜色,颜色矩阵是一个5x4 的矩阵
第一行决定红色、第二行决定绿色、第三行决定蓝色、第四行决定了透明度。第五是颜色的偏移量。 颜色矩阵以一维数组的方式存储如下: [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ] 他通过RGBA四个通道来直接操作对应颜色,如果会使用Photoshop就会知道有时处理图片通过控制RGBA各颜色通道来做出特殊的效果。

而图像的RGBA值则存储在一个5*1的颜色分量矩阵C中,由颜色分量矩阵C可以控制图像的颜色效果

  


要想改变一张图片的颜色效果,只需要改变图像的颜色分量矩阵即可。通过颜色矩阵可以很方便的修改图像的颜色分量矩阵。假设修改后的图像颜色分量矩阵为C1,则有如下图所示的颜色分量矩阵计算公式。
矩阵的运算规则是:矩阵M的一行乘以矩阵C的一列作为矩阵R的一行。 M是颜色矩阵,C矩阵是图片中包含的RGBA信息,R矩阵是用M应用于C之后的新的颜色分量。
由此可见,通过颜色矩阵修改了原图像的RGBA值,从而达到了改变图片颜色效果的目的。并且,通过上图所示的运算可知,颜色矩阵M的第一行参数abcde决定了图像的红色成分,第二行参数fghij决定了图像的绿色成分,第三行参数klmno决定了图像的蓝色成分,第四行参数pqrst决定了图像的透明度,第五列参数ejot是颜色的偏移量。
通常,改变颜色分量时可以通过修改第5列的颜色偏移量来实现,如下图所示的颜色矩阵M1,通过计算后可以得知该颜色矩阵的作用是使图像的红色分量和绿色分量均增加100,这样的效果就是图片泛黄(因为红色与绿色混合后得到黄色)。


除此之外,也可以通过直接对颜色值乘以某一系数而达到改变颜色分量的目的。如下图所示的颜色矩阵M2,将绿色分量放大了2倍,这样的效果就是图片泛绿色。


效果演示
 
    
 
    
 



调色器代码
 
    
 
    
public class MainActivity extends Activity implements OnSeekBarChangeListener, OnClickListener {
    private ImageView imageView;
    private SeekBar sb_redsb_greensb_bluesb_brightnesssb_saturation;
    private Bitmap preBitmapafterBitmap;
    private Canvas canvas;
    private ColorMatrix colorMatrixrgbMatrixhuduMatrix;
    private Paint paint;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.iv);
        findViewById(R.id.btn_select).setOnClickListener(this);
        findViewById(R.id.btn_save).setOnClickListener(this);
        sb_red = (SeekBar) findViewById(R.id.sb_red);
        sb_green = (SeekBar) findViewById(R.id.sb_green);
        sb_blue = (SeekBar) findViewById(R.id.sb_blue);
        sb_brightness = (SeekBar) findViewById(R.id.sb_brightness);
        sb_saturation = (SeekBar) findViewById(R.id.sb_saturation);
        sb_red.setOnSeekBarChangeListener(this);
        sb_green.setOnSeekBarChangeListener(this);
        sb_blue.setOnSeekBarChangeListener(this);
        sb_brightness.setOnSeekBarChangeListener(this);
        sb_saturation.setOnSeekBarChangeListener(this);
        paint = new Paint();
        colorMatrix = new ColorMatrix();//5*4的颜色矩阵
        rgbMatrix = new ColorMatrix();//RGB颜色及亮度
        huduMatrix = new ColorMatrix();//饱和度或灰度
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {//进度改变时调用
        if (preBitmap != null) {
            float progressR = sb_red.getProgress() / 128f;//这里处理后值的范围为[0,2],初始值是1,也即初始时不做任何改变。
            float progressG = sb_green.getProgress() / 128f;
            float progressB = sb_blue.getProgress() / 128f;
            float progressA = sb_brightness.getProgress() / 128f;
            float progressS = sb_saturation.getProgress() / 128f;
            float[] values = new float[] { progressR, 0, 0, 0, 0,//
                    0, progressG, 0, 0, 0,//
                    0, 0, progressB, 0, 0,//
                    0, 0, 0, progressA, 0 };//
            //1、改变色相及亮度
            rgbMatrix.set(values);
            //2、改变饱和度、透明度、灰度。当饱和度=0时,会变成黑白图片(有灰度的黑白照片)。
            huduMatrix.setSaturation(progressS);
            //3、要想将色彩三元素综合运用到一张图片上,需要通过颜色矩阵的postConcat方法将三元素进行连接。
            colorMatrix.reset();//要重置一下才可以,不然等于是在之前的基础上进行的更改
            colorMatrix.postConcat(rgbMatrix); //这里其实是将两个矩阵进行了运算,熟悉矩阵运算的应该知道,先后顺序是有重大影响的
            colorMatrix.postConcat(huduMatrix);
            //4、通过颜色滤镜将颜色矩阵应用于图片上
            paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
            canvas.drawBitmap(preBitmapnew Matrix(), paint);
            imageView.setImageBitmap(afterBitmap);
        } else Toast.makeText(getApplicationContext(), "清先选择一张图片再调整颜色", 0).show();
    }
    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {//开始拖动时调用
    }
    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {//结束拖动时调用
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.btn_select// 激活系统图库,选择一张图片
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_PICK);
            intent.setType("image/*");
            startActivityForResult(intent, 0);
            break;
        case R.id.btn_save//保存bitmap为图片
            File file = new File(Environment.getExternalStorageDirectory(), new SimpleDateFormat("yyyy.MM.dd HH-mm-ss",  Locale. getDefault ()).format( new  Date())  +  ".png" );
            try {
                FileOutputStream out = new FileOutputStream(file);
                afterBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
                out.close();
            } catch (Exception e) {
                Toast.makeText(this"保存出现异常", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
            break;
        }
    }

    //返回一张照片后初始化afterBitmap
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (data != null && data.getData() != null) {
            try {
                Uri uri = data.getData();// 得到图片的全路径。相机目录下的某个文件的路径为:content://media/external/images/media/12718
                Log.i("bqt""路径为:" + uri);//SD卡根目录下的文某个文件的件路径为:content://media/external/images/media/12758
                InputStream is = getContentResolver().openInputStream(uri);//获取文件的流
                preBitmap = BitmapFactory.decodeStream(is); //通过流加载图片
            } catch (FileNotFoundException e) {
            }
            // 创建一张可以被修改的空白图片
            afterBitmap = Bitmap.createBitmap(preBitmap.getWidth(), preBitmap.getHeight(), preBitmap.getConfig());
            canvas = new Canvas(afterBitmap);
            canvas.drawBitmap(preBitmapnew Matrix(), paint);//先把原图绘制上去,目的仅仅是让你预览一下
            imageView.setImageBitmap(afterBitmap);//注意imageView上显示的不是我们本地的图片,而是我们内存中刚刚new的Bitmap
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

调色器布局
 
    
 
    
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <SeekBar
        android:id="@+id/sb_red"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="128" />
    <SeekBar
        android:id="@+id/sb_green"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="128" />
    <SeekBar
        android:id="@+id/sb_blue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="128" />
    <SeekBar
        android:id="@+id/sb_brightness"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="128" />
    <SeekBar
        android:id="@+id/sb_saturation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="128" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <Button
            android:id="@+id/btn_select"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="选择一张照片" />
        <Button
            android:id="@+id/btn_save"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="保存图片到SD卡" />
    </LinearLayout>
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

颜色矩阵演示
 
    
 
    



颜色矩阵代码
 
     
 
     
public class MainActivity extends Activity implements OnClickListener {
    private Paint myPaint;
    private Bitmap bitmapalterBitmap;
    private Canvas canvas;
    private ColorMatrix myColorMatrix;
    private ImageView iv;
    private EditText[] editTextArray = new EditText[20];
    private float[] colorArray = new float[20];
    private int[] EditTextID = { R.id.Edit1, R.id.Edit2, R.id.Edit3, R.id.Edit4, R.id.Edit5, R.id.Edit6, R.id.Edit7, R.id.Edit8,
            R.id.Edit9, R.id.Edit10, R.id.Edit11, R.id.Edit12, R.id.Edit13, R.id.Edit14, R.id.Edit15, R.id.Edit16, R.id.Edit17,
            R.id.Edit18, R.id.Edit19, R.id.Edit20 };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.Button).setOnClickListener(this);
        iv = (ImageView) findViewById(R.id.iv);
        for (int i = 0; i < 20; i++) {
            editTextArray[i] = (EditText) findViewById(EditTextID[i]);
        }
        myPaint = new Paint();
        myColorMatrix = new ColorMatrix();
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.a);
        iv.setImageBitmap(bitmap);//先用旧图装饰一下门面
    }

    @Override
    public void onClick(View v) {
        for (int i = 0; i < 20; i++) {
            String num = editTextArray[i].getText().toString().trim();
            if (TextUtils.isEmpty(num)) colorArray[i] = 0;
            else colorArray[i] = Float.valueOf(num);
        }
        //每提交一次都要重新设置以下alterBitmap,不然等于是在上次的基础上修改了
        alterBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
        canvas = new Canvas(alterBitmap);
        //必须先把原图画上去,然后才能通过颜色矩阵修改图片的颜色
        canvas.drawBitmap(bitmapnew Matrix(), new Paint());//注意这里的Paint不能直接使用myPaint,否则会重复绘制颜色滤镜。当然使用之前重置一下就可以用了。
        //设置颜色矩阵
        myColorMatrix.set(colorArray);
        myPaint.setColorFilter(new ColorMatrixColorFilter(myColorMatrix));
        canvas.drawBitmap(alterBitmap, 0, 0, myPaint);
        iv.setImageBitmap(alterBitmap);
    }
}

颜色矩阵布局
 
     
 
     
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_gravity="center" />
    <Button
        android:id="@+id/Button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="提交" />
    <LinearLayout
        android:id="@+id/colorlayout1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/Edit1"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal"
            android:text="1" />
        <EditText
            android:id="@+id/Edit2"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit3"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit4"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit5"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/colorlayout2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/Edit6"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit7"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal"
            android:text="1" />
        <EditText
            android:id="@+id/Edit8"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit9"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit10"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/colorlayout3"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/Edit11"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit12"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit13"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal"
            android:text="1" />
        <EditText
            android:id="@+id/Edit14"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit15"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/colorlayout4"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
        <EditText
            android:id="@+id/Edit16"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit17"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit18"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
        <EditText
            android:id="@+id/Edit19"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal"
            android:text="1" />
        <EditText
            android:id="@+id/Edit20"
            android:layout_width="50dp"
            android:layout_height="40dp"
            android:layout_weight="1"
            android:numeric="decimal" />
    </LinearLayout>
</LinearLayout>





转载于:https://www.cnblogs.com/baiqiantao/p/5491800.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: imatest是一种用于校准color matrix的工具。Color matrix是一种矩阵,用于将图像的颜色表达方式从一种颜色空间转换为另一种颜色空间。通过使用imatest,我们可以验证color matrix的准确性和有效性。 首先,我们需要采集一组已知颜色和亮度的样本图像。这些样本图像可以代表各种真实世界的场景和颜色。然后,我们将这些样本输入到imatest中,以便它可以分析每个图像的颜色信息。 imatest会根据样本图像中的已知颜色和亮度值,计算出实际的颜色矩阵。然后,它会将这些实际矩阵与目标矩阵进行比较,以确定color matrix的准确性和效果。 如果经过校验后,imatest认为color matrix的结果与目标矩阵接近,那么我们可以确定color matrix已经校准好了。否则,我们需要调整color matrix的参数和设置,然后再次使用imatest进行校验,直到达到我们期望的结果为止。 imatest不仅可以用于校准color matrix,还可以用于测试和验证其他图像处理算法和技术的准确性和效果。对于图像处理领域的研究人员和工程师来说,imatest是一个非常有用的工具,可以帮助他们评估和优化算法和技术的性能。 ### 回答2: imatest的校准colormatrix是一个重要的步骤,用于确保图像的颜色准确性和一致性。colormatrix是一个矩阵,它定义了图像传感器捕捉到的原始颜色值与最终显示的颜色之间的转换关系。 在校准过程中,imatest首先使用一组已知颜色的测试图像来捕捉图像传感器的原始颜色数据。然后,通过对这些原始颜色数据执行数学运算,imatest根据一系列标准颜色值和色差计算方法,推导出用于校准colormatrix的转换矩阵。 为了确保校准的准确性,imatest还需要校准的测试设备具备高精度的色度测量仪器和标准参考图像。校准过程中要充分考虑光源、环境和设备参数等因素的影响。 一旦校准colormatrix完成,图像处理软件或硬件将使用这个校准矩阵将原始传感器数据转换为准确的显示颜色。这样可以确保图像的颜色准确无误,并且保证在不同的硬件或软件上显示的图像具有一致的色彩表现。 总的来说,imatest的校准colormatrix是一个关键的过程,它可以确保图像颜色的正确性和一致性,从而提高图像的质量和可靠性。 ### 回答3: IMATEST是一种用于校准颜色矩阵的测试工具。颜色矩阵校准是图像处理中的重要步骤,它可以准确地调整图像的色彩均衡,使颜色显示更加准确和真实。IMATEST校ColorMatrix算法通过比较参考图像和待校准图像之间的色彩差异来进行校准。 使用IMATEST校ColorMatrix,首先需要准备一个参考图像和一个待校准图像。这两个图像应该是相同的场景,但在色彩方面可能存在差异。然后,将这两个图像输入到IMATEST软件中,开始进行校准。 IMATEST校ColorMatrix通过分析参考图像和待校准图像之间的色彩差距来确定最佳的颜色矩阵校准参数。它会自动调整颜色矩阵的各个参数,直到两个图像的色彩差异最小化。校准过后,待校准图像的色彩就会变得更加准确,与参考图像更为接近。 IMATEST校ColorMatrix的优点在于它能够自动化处理校准过程,帮助用户节省时间和精力。它还提供了一些可调整的参数,如对比度和饱和度,以便进一步调整图像的色彩效果。 总之,IMATEST校ColorMatrix是一种有效的校准颜色矩阵的测试工具,通过比较参考图像和待校准图像的色彩差异来实现图像色彩的准确性和真实性。它是图像处理领域中重要的工具之一,可被广泛应用于摄影、电影制作、印刷等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值