
之前写了一篇博客,是关于用python的turtle库实现自动画图的程序。有兴趣的可以去看一下,博客链接:python使用turtle实现自动绘图
演示视频:
海龟画图python
20211222
最近我将这个画图的程序部署到移动端上,从相册中选择图像,然后实现自动绘制。
app下载。
移动端上的演示视频:
自动绘图
下面分析一下绘图的主要代码:
mainactivity.java
package com.myapp.drawpic2;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationManagerCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
//import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
//import android.util.Log;
import android.util.Log;
import android.view.View;
import android.widget.Button;
//import android.widget.FrameLayout;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
//import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONObject;
import org.opencv.android.OpenCVLoader;
//import org.opencv.android.Utils;
//import org.opencv.core.CvType;
import org.opencv.core.Mat;
import cn.jpush.android.api.JPushInterface;
//import org.opencv.core.MatOfPoint;
//import org.opencv.core.Point;
//import org.opencv.dnn.Net;
//import org.opencv.imgproc.Imgproc;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Timer;
//import java.util.TimerTask;
//import java.util.logging.Handler;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
//极光推送
//for receive customer msg from jpush server
private MessageReceiver mMessageReceiver;
public static final String MESSAGE_RECEIVED_ACTION = "com.myapp.drawpic2.MESSAGE_RECEIVED_ACTION";
public static final String KEY_TITLE = "title";
public static final String KEY_MESSAGE = "message";
public static final String KEY_EXTRAS = "extras";
private EditText msgText;
private Bitmap bmp;
private Mat src;
private Mat dst;
private Canvas mcanvas;
private Paint paint;
private Path path;
private Button btn;
private Button camera;
private Button draw;
private ImageView imageView;
private Bitmap bitmap;
private Bitmap mybmp;
private MyView vie;
private ImageView waring;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JPushInterface.init(getApplicationContext());//极光接口初始化,否则用不了
registerMessageReceiver();//注册消息接收器
iniLoadOpenCV();
if (!isNotificationEnabled(this)){
gotoSet();
}else {
//允许通知
}
waring=findViewById(R.id.waring);
RelativeLayout relativeLayout=findViewById(R.id.relate);
btn=findViewById(R.id.btn);
draw=findViewById(R.id.btn2);
btn.setVisibility(View.VISIBLE);
draw.setVisibility(View.VISIBLE);
imageView=findViewById(R.id.image);
// HandPic handPic=new HandPic(this);
// relativeLayout.addView(handPic);
waring.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(MainActivity.this,Waring.class);
startActivity(intent);
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
relativeLayout.addView(waring);
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, 2);
//移除组件
if(vie!=null){
relativeLayout.removeView(vie);
}
}
});
draw.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
relativeLayout.removeView(vie);
} catch (Exception e) {
e.printStackTrace();
}
relativeLayout.removeView(waring);
//获取bitmap
imageView.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(imageView.getDrawingCache());
imageView.setDrawingCacheEnabled(false);
vie=new MyView(MainActivity.this,bitmap);
relativeLayout.addView(vie);
// btn.setVisibility(View.INVISIBLE);
// draw.setVisibility(View.INVISIBLE);
}
});
// bmp= BitmapFactory.decodeResource(getResources(),R.drawable.b2);
// imageView=findViewById(R.id.image1);
// imageView.setImageBitmap(bmp);
//
// //bitmap转mat
// src=new Mat();
// dst=new Mat();
// Utils.bitmapToMat(bmp,src);
// //灰度化
// Imgproc.cvtColor(src,src,Imgproc.COLOR_RGBA2GRAY);
// //二值化
// Imgproc.threshold(src,src,0,255,8);
// //开运算
// Mat keral=Mat.ones(7,7, CvType.CV_8UC1);
// Imgproc.morphologyEx(src,src,Imgproc.MORPH_OPEN,keral);
// Utils.matToBitmap(src,bmp);
// List contours=new ArrayList<>();
// Mat mm=new Mat();
// Imgproc.findContours(src,contours,mm,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE);
// Log.i("aa",String.valueOf(contours.get(0).toList()));
//
// paint=new Paint();
// paint.setStrokeWidth(3);
// //设置不填充
paint.setStyle(Paint.Style.STROKE);
android.graphics.Bitmap.Config bitmapConfig = bmp.getConfig();
Bitmap bp = bmp.copy(bitmapConfig, true);
mcanvas=new Canvas(bp);
//
// Bitmap bp=Bitmap.createBitmap(bmp.getWidth(),bmp.getHeight(),Bitmap.Config.ARGB_8888);
// //将白板图像显示到界面上
// imageView.setImageBitmap(bp);
// //画图
// mcanvas=new Canvas(bp);
// for (MatOfPoint points:contours){
// List lieb=points.toList();
//
// path=new Path();
// for (int i=0; i
// if (i==0){
// path.moveTo((float)lieb.get(i).x,(float)lieb.get(i).y);
Log.i("aa",""+lieb.get(i).x+" "+lieb.get(i).y);
// }else {
// path.lineTo((float)lieb.get(i).x,(float)lieb.get(i).y);
//
// Log.i("aa",""+lieb.get(i).x+" "+lieb.get(i).y);
// };
// mcanvas.drawCircle(500,500,i+1,paint);
//
// };
// mcanvas.drawCircle(500,500,1000,paint);
// mcanvas.drawPath(path, paint);
// }
// mcanvas.drawCircle(500,500,500,paint);
// Log.i("aa",String.valueOf(contours.get(0).toList().get(0).x));
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
//opencv初始化
private void iniLoadOpenCV(){
boolean success= OpenCVLoader.initDebug();
if (success){
// Toast.makeText(this.getApplicationContext(),"Load OpenCV Succesful",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(this.getApplicationContext(),"Load OpenCV Failed",Toast.LENGTH_LONG).show();
}
}
private Uri uri;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2) {
// 从相册返回的数据
// Log.e(this.getClass().getName(), "Result:" + data.toString());
if (data != null) {
// 得到图片的全路径
try{
uri = data.getData();
imageView.setImageURI(uri);
} catch (Exception e) {
e.printStackTrace();
}
// imageView.setImageURI(uri);
// Log.e(this.getClass().getName(), "Uri:" + String.valueOf(uri));
// Log.i("aa",""+uri);
}
}
}
public void registerMessageReceiver() {
mMessageReceiver = new MessageReceiver();
IntentFilter filter = new IntentFilter();
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
filter.addAction(MESSAGE_RECEIVED_ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, filter);
}
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) {
String messge = intent.getStringExtra(KEY_MESSAGE);
String extras = intent.getStringExtra(KEY_EXTRAS);
StringBuilder showMsg = new StringBuilder();
showMsg.append(KEY_MESSAGE + " : " + messge + "\n");
if (!ExampleUtil.isEmpty(extras)) {
showMsg.append(KEY_EXTRAS + " : " + extras + "\n");
}
setCostomMsg(showMsg.toString());
}
} catch (Exception e){
}
}
}
//设置自定义消息
private void setCostomMsg(String msg){
if (null != msgText) {
msgText.setText(msg);
msgText.setVisibility(View.VISIBLE);
}
}
//是否开启通知接收
private boolean isNotificationEnabled(Context context) {
boolean isOpened = false;
try {
isOpened = NotificationManagerCompat.from(context).areNotificationsEnabled();
} catch (Exception e) {
e.printStackTrace();
isOpened = false;
}
return isOpened;
}
//去设置
private void gotoSet() {
Intent intent = new Intent();
if (Build.VERSION.SDK_INT >= 26) {
// android 8.0引导
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", getPackageName());
} else if (Build.VERSION.SDK_INT >= 21) {
// android 5.0-7.0
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("app_package", getPackageName());
intent.putExtra("app_uid", getApplicationInfo().uid);
} else {
// 其他
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.fromParts("package", getPackageName(), null));
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
绘制图像的代码都在myview.java中。
myview.java
package com.myapp.drawpic2;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposePathEffect;
import android.graphics.CornerPathEffect;
import android.graphics.DashPathEffect;
import android.graphics.DiscretePathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.PathEffect;
import android.graphics.SumPathEffect;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;
import org.opencv.imgproc.Imgproc;
import java.util.ArrayList;
import java.util.List;
class MyView extends View {
float phase;
private Paint paint;
Path path;
Path path2;
private Bitmap bmp;
// private Bitmap mybmp;
private Canvas mCanvas;
private int pic_width;
private int pic_height;
private int view_width;
private int view_height;
private Bitmap hand_bmp;
public MyView(Context context,Bitmap mybmp) {
super(context);
handx=500;
handy=500;
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
paint.setColor(0xFFFFFFFF);
path = new Path();
path2 = new Path();
pic_width=mybmp.getWidth();
pic_height=mybmp.getHeight();
// path.moveTo(0, 0);
// mybmp= BitmapFactory.decodeResource(getResources(),R.drawable.b2);
counter=findcounters(mybmp);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
view_width= getMeasuredWidth();
view_height= getMeasuredHeight();
// Log.i("aa","窗口宽高"+width1+" "+height1);
// Log.i("aa","图片宽高"+width+" "+height);
bmp=Bitmap.createBitmap(view_width,view_height,Bitmap.Config.ARGB_8888);
mCanvas=new Canvas(bmp);
mCanvas.drawColor(Color.BLACK);
}
float x;
float y;
float u=0;
float v;
private List<MatOfPoint> counter;
int con=0;
int zbiao=0;
private boolean first_count;
private boolean first_point;
private Mat mat=new Mat();
float handx;
float handy;
@Override
protected void onDraw(Canvas canvas) {
//创建并初始化Path
//将背景色填充成白色
// canvas.drawColor(Color.WHITE);
if (con<counter.size()){
List<Point> points=counter.get(con).toList();
//寻找填充值
MatOfPoint matOfPoint=counter.get(con);
//寻找最左边的x坐标
mat=matOfPoint.reshape(1,matOfPoint.rows());
Mat mat_x=mat.colRange(0,1);
Core.MinMaxLocResult out=Core.minMaxLoc(mat_x);
double minx_value=out.minVal;
Point index_min=out.minLoc;
double maxx_value=out.maxVal;
Point index_max=out.maxLoc;
int[] xy=new int[2];
mat.get((int)index_min.y,0,xy);
byte[] data=new byte[src.cols()];
src.get(xy[1],0,data);
if(xy[0]+1<data.length){
int yy=data[xy[0]+1];
if(yy!=0){
//填充白色
paint.setColor(0xFFFFFFFF);
}else {
paint.setColor(0xFF000000);
}
// paint.setStyle(Paint.Style.FILL);
// mCanvas.drawPath(path2,paint);
Log.i("aa",yy+"");
}
// Mat mat2=mat.rowRange((int)index_min.y,(int)index_min.y+1);
if (zbiao<points.size()){
x=(float)points.get(zbiao).x;
y=(float)points.get(zbiao).y;
// Log.i("aa",x+" "+y);
x=x*((float) view_width/(float) pic_width);
y=y*((float) view_height/(float) pic_height);
//确定轮廓的第一个坐标
if (zbiao==0){
path.moveTo((int)x,(int)y);
path2.moveTo((int)x,(int)y);
}else {
path.lineTo((int)x,(int)y);
path2.lineTo((int)x,(int)y);
}
// Log.i("aa",x+" "+y);
zbiao++;
}else {
paint.setStyle(Paint.Style.FILL);
mCanvas.drawPath(path2,paint);
path = new Path();
path2 = new Path();
zbiao=0;
con++;
}
}else {
con=counter.size();
}
paint.setStyle(Paint.Style.STROKE);
mCanvas.drawPath(path,paint);
// Log.i("aa",""+counter.size()+" "+con);
canvas.drawBitmap(bmp,0,0,null);
hand_bmp= BitmapFactory.decodeResource(this.getResources(),R.mipmap.hand);
handx=x-30;
handy=y-30;
if (con<counter.size()){
canvas.drawBitmap(hand_bmp,handx,handy,paint);
}
invalidate();
}
private Mat src;
private List<MatOfPoint> findcounters(Bitmap bmp){
// bmp= BitmapFactory.decodeResource(getResources(),R.drawable.b2);
//bitmap转mat
src=new Mat();
Utils.bitmapToMat(bmp,src);
//灰度化
Imgproc.cvtColor(src,src,Imgproc.COLOR_RGBA2GRAY);
//二值化
Imgproc.threshold(src,src,0,255,8);
//开运算
// Mat keral=Mat.ones(7,7, CvType.CV_8UC1);
// Imgproc.morphologyEx(src,src,Imgproc.MORPH_OPEN,keral);
Utils.matToBitmap(src,bmp);
List<MatOfPoint> contours=new ArrayList<>();
Mat mm=new Mat();
Imgproc.findContours(src,contours,mm,Imgproc.RETR_TREE,Imgproc.CHAIN_APPROX_SIMPLE);
return contours;
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)