写的一个关于颜色识别的小功能。识别主要颜色。
思路:遍历像素点,找出出现次数最多的像素值作为主要颜色。
采用的方法有:
1.调用摄像头,拍照,裁剪,压缩。
2.找出色值。
3.转换成hsv空间,进行颜色判断
4.异步显示,主要是为了防止遍历图片时出现界面卡死的现象。颜色图片展示在imageview里,颜色信息用textview显示
搬了很多砖,最终可以了嘻嘻
MainActivity代码:
package com.example.newcolor;import androidx.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;public class MainActivity extends Activity {private ImageView iv;private Button button;private File file;private Uri uri;private TextView textview;int width;int height;int color=255;String str="";Handler handler=new Handler(){@Overridepublic void handleMessage(@NonNull Message msg) {super.handleMessage(msg);if(msg.what==0x123){Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.RGB_565);bitmap.eraseColor(color);//填充颜色iv.setImageBitmap(bitmap); // 将裁剪后的照片显示出来textview.setText(str);}}};protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);iv = (ImageView) findViewById(R.id.imageView1);button = (Button) findViewById(R.id.button1);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();StrictMode.setVmPolicy( builder.build() );}file = new File(this.getExternalFilesDir(null), "image.jpg");uri = Uri.fromFile(file);textview=(TextView) findViewById(R.id.textView);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);startActivityForResult(intent, 2);}});}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stubsuper.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {if (requestCode == 2) {startPhotoZoom(uri);} else {try {processThread();}catch (Exception e) {// TODO: handle exception}}}}/*** 裁剪图片** @param uri*/public void startPhotoZoom(Uri uri) {Intent intent = new Intent("com.android.camera.action.CROP");intent.setDataAndType(uri, "image/*");intent.putExtra("crop", "true");// crop=true 有这句才能出来最后的裁剪页面.intent.putExtra("aspectX", 1);// 这两项为裁剪框的比例.intent.putExtra("aspectY", 1);// x:y=1:1intent.putExtra("outputX", 200);//图片输出大小intent.putExtra("outputY", 200);intent.putExtra("output", uri);intent.putExtra("outputFormat", "JPEG");// 返回格式startActivityForResult(intent, 3);}/*** 将图片image压缩成大小为 size的图片(size表示图片大小,单位是KB)** @param image* 图片资源* @param size* 图片大小* @return Bitmap*/private Bitmap compressImage(Bitmap image, int size) {ByteArrayOutputStream baos = new ByteArrayOutputStream();// 质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中image.compress(Bitmap.CompressFormat.JPEG, 100, baos);int options = 100;// 循环判断如果压缩后图片是否大于100kb,大于继续压缩while (baos.toByteArray().length / 1024 > size) {// 重置baos即清空baosbaos.reset();// 每次都减少10options -= 10;// 这里压缩options%,把压缩后的数据存放到baos中image.compress(Bitmap.CompressFormat.JPEG, options, baos);}// 把压缩后的数据baos存放到ByteArrayInputStream中ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把ByteArrayInputStream数据生成图片Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);return bitmap;}private void processThread(){//构建一个下载进度条new Thread(){@Overridepublic void run(){Log.i("tag", "run()-->"+Thread.currentThread().getName());//在新线程里执行长耗时方法BitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 2;Bitmap mBitmap = BitmapFactory.decodeFile(file.getPath(), options);width = mBitmap.getWidth();height = mBitmap.getHeight();// 保存所有的像素的数组,图片宽×高int[] pixels = new int[width * height];mBitmap.getPixels(pixels, 0, width, 0, 0, width, height);HashMap<Integer,Integer> color2=new HashMap<Integer, Integer>();for (Integer color:pixels){if (color2.containsKey(color)){Integer integer = color2.get(color);integer++;color2.remove(color);color2.put(color,integer);}else{color2.put(color,1);}}//挑选数量最多的颜色Iterator iter = color2.entrySet().iterator();int count=0;while (iter.hasNext()) {Map.Entry entry = (Map.Entry) iter.next();int value = (Integer) entry.getValue();if (count<value){count=value;color= (Integer) entry.getKey();}}float[] hsv = new float[3];int r = Color.red(color);int g = Color.green(color);int b = Color.blue(color);Color.RGBToHSV(r, g, b, hsv);float h=hsv[0]/2;float s=hsv[1]*255;float v=hsv[2]*255;System.out.println(hsv[0]/2);if ((h>= 0 && h<= 180)&& (s >= 0 && s<= 255)&& (v>= 0 && v<= 46)){System.out.println("black");str="black";}else if ((h >= 0 && h <= 180)&& (s >= 0 && s<= 43)&& (v>= 46 && v<= 220)){System.out.println("grey");str="grey";}else if ((h>= 0 && h<= 180)&& (s>= 0 && s<= 30)&& (v>= 221 && v <= 255)){System.out.println("white");str="white";}else if (((h>= 0 && h<= 10) || (h>= 156 && h <= 180))&& (s>= 43 && s <= 255)&& (v>= 46 && v <= 255)){System.out.println("red");str="red";}else if((h>=11&&h<=25)&&(s>=43&&s<=255)&&(v>=46&&v<=255)){System.out.println("orange");}else if ((h>= 26 && h <= 34)&& (s>= 43 && s <= 255)&& (v>= 46 && v<= 255)){System.out.println("yellow");str="yellow";}else if((h>=35&&h<=77)&&(s>=43&&s<=255)&&(v>=46&&v<=255)){System.out.println("green");str="green";}else if((h>=78&&h<=99)&&(s>=43&&s<=255)&&(v>=46&&v<=255)){System.out.println("qing");str="qing";}else if((h>=100&&h<=124)&&(s>=43&&s<=255)&&(v>=46&&v<=255)){System.out.println("blue");str="blue";}else if((h>=125&&h<=155)&&(s>=43&&s<=255)&&(v>=46&&v<=255)){System.out.println("purple");str="purple";}else{System.out.println("颜色库会进行相应补充");str="颜色库会进行相应补充";}//执行完毕后给handler发送一个空消息handler.sendEmptyMessage(0x123);}}.start();}}
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"><ImageViewandroid:id="@+id/imageView1"android:layout_width="200dp"android:layout_height="200dp"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:layout_marginTop="64dp"/><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@+id/imageView1"android:layout_centerHorizontal="true"android:layout_marginTop="174dp"android:text="颜色识别" /><TextViewandroid:id="@+id/textView"android:layout_width="match_parent"android:layout_height="48dp"android:text="TextView" /></RelativeLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.newcolor"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>
效果展示: