写的一个关于颜色识别的小功能。识别主要颜色。
思路:遍历像素点,找出出现次数最多的像素值作为主要颜色。
采用的方法有:
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(){
@Override
public 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() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, 2);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.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:1
intent.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即清空baos
baos.reset();
// 每次都减少10
options -= 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(){
@Override
public 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">
<ImageView
android:id="@+id/imageView1"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="64dp"
/>
<Button
android: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="颜色识别" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="48dp"
android:text="TextView" />
RelativeLayout>
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.newcolor">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android: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>