AndroidStudio实现在图片上涂鸦并记录涂鸦轨迹

AndroidStudio实现在图片上涂鸦,并保存涂鸦轨迹

开个坑,终于有时间整理一下这个项目里用到的比较重要的技术
虽然最后甲方没有采用(笑)
因为博主学艺不精,有很多小bug

AndroidStudio版本:2020.3.1.25
实现效果:请添加图片描述
本文通过重写view类,实现在选择的图片上涂鸦的功能,因为项目需要残留了一些多余代码
项目结构:
MainActivity为主程序类
HandWrite类为手写类,用于处理各种手势
res/layout/activity_main.xml 为主界面
res/xml/file_path.xml 为图片缓存路径
在这里插入图片描述

0.Handwrite类

划重点,此类中重写了view类,画出了手指按下的轨迹,并记录在pointlist中

package com.buildmaterialapplication;import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;import java.util.ArrayList;public class HandWrite extends View {Paint paint = null;  //定义画笔Bitmap origBit = null;  //存放原始图像Bitmap new_1Bit = null;   //存放从原始图像复制的位图图像Bitmap new_2Bit = null;      //存放处理后的图像float startX = 0,startY = 0;   //画线的起点坐标float clickX = 0, clickY = 0;   //画线的终点坐标boolean isMove = false;   //设置是否画线的标记boolean isDown =false;boolean isClear = false;    //设置是否清除涂鸦的标记int color = Color.BLUE;    //设置画笔的颜色float strokeWidth = 4.0f;    //设置画笔的宽度private int pen_type=0;ArrayList<Point> pointList =new ArrayList();Point point=new Point();public HandWrite(Context context, AttributeSet arrs){super(context,arrs);}//设置画笔类型public void setPen_type(int x) {pen_type = x;Log.e("penType",Integer.toString(pen_type));}//构造public HandWrite(Context context, Bitmap bm, int type) {super(context);// 从资源中获取原始图像//origBit = BitmapFactory.decodeFile("/storage/emulated/0/Android/data/com.example.test/cache/19771639479845774.jpg").copy(Bitmap.Config.ARGB_8888,true);origBit=Bitmap.createBitmap(bm).copy(Bitmap.Config.ARGB_8888,true);//origBit = BitmapFactory.decodeResource(getResources(), R.drawable.p1).copy(Bitmap.Config.ARGB_8888,true);// 建立原始图像的位图new_1Bit = Bitmap.createBitmap(origBit);pen_type=type;}public Point getPoint() {return point;}public ArrayList<Point> getPointList() {return pointList;}// 清除涂鸦public void clear() {isClear = true;new_2Bit = Bitmap.createBitmap(origBit);invalidate();}//设置画笔样式public void setSytle(float strokeWidth) {this.strokeWidth = strokeWidth;this.color=Color.BLUE;}//重写ondraw方法@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawBitmap(HandWriting(new_1Bit),0,0,null);}private Bitmap HandWriting(Bitmap origBit) {  //记录绘制图形Canvas canvas = null;  // 定义画布if (isClear) {  // 创建绘制新图形的画布canvas = new Canvas(new_2Bit);}else {canvas = new Canvas(origBit);  //创建绘制原图形的画布}paint = new Paint();paint.setStyle(Paint.Style.STROKE);paint.setAntiAlias(true);paint.setColor(color);paint.setStrokeWidth(strokeWidth);//lassoif (isMove&&(pen_type==3)){canvas.drawLine(startX,startY,clickX,clickY,paint);  // 在画布上画线条}//eraserif (isMove&&pen_type==2){paint.setAlpha(70);paint.setStrokeWidth(40.0f);paint.setStyle(Paint.Style.FILL);canvas.drawLine(startX,startY,clickX,clickY,paint);  // 在画布上画线条}startX = clickX;startY = clickY;//penif (pen_type==1){if(isDown){paint.setColor(Color.GREEN);paint.setStyle(Paint.Style.FILL);canvas.drawCircle(clickX,clickY,20.0f,paint);}}//点击的eraserif (isDown&&pen_type==2){paint.setColor(Color.BLUE);canvas.drawCircle(clickX,clickY,20.0f,paint);}if (isClear){return new_2Bit;  // 返回新绘制的图像}return origBit;  // 若清屏,则返回原图像}@Overridepublic boolean onTouchEvent(MotionEvent event) {final int historySize = event.getHistorySize();final int pointerCount = event.getPointerCount();for (int h = 0; h < historySize; h++) {
//            Log.e("At time %d:", (event.getHistoricalEventTime(h)));for (int p = 0; p < pointerCount; p++) {/*System.out.printf("  pointer %d: (%f,%f)",event.getPointerId(p), event.getHistoricalX(p, h), event.getHistoricalY(p, h));*/int po=(event.getPointerId(p));Float ghx=event.getHistoricalX(p, h);Float ghy=event.getHistoricalY(p, h);String pointer =Integer.toString(po);String x=Float.toString(ghx);String y=Float.toString(ghy);String tmp1=pointer+x+y;
//                Log.e("pointer1",tmp1);}}int time= (int) event.getEventTime();
//        String tmp2=Integer.toString(time);
//        Log.e("time",tmp2);//System.out.printf("At time %d:", event.getEventTime());//获取点集for (int p = 0; p < pointerCount; p++) {int po=(event.getPointerId(p));int ghx=(int) event.getX(p);int ghy=(int) event.getY(p);Point point=new Point(ghx,ghy);if(!pointList.contains(point)){if(pen_type!=2){pointList.add(p,point);int x=pointList.get(p).x;int y=pointList.get(p).y;Log.e("po",Integer.toString(x)+" "+Integer.toString(y));}}
//            String pointer =Integer.toString(po);/*System.out.printf("  pointer %d: (%f,%f)",event.getPointerId(p), event.getX(p), event.getY(p));*/}clickX = event.getX();  // 获取触摸坐标位置clickY = event.getY();if(event.getAction() == MotionEvent.ACTION_DOWN){isMove=false;isDown=true;invalidate();return true;}else if (event.getAction() == MotionEvent.ACTION_MOVE) {  // 记录在屏幕上划动的轨迹isMove = true;isDown=false;invalidate();return true;}if(event.getAction()==MotionEvent.ACTION_UP){performClick();invalidate();return true;}return super.onTouchEvent(event);}
}

1.activity_main.xml界面

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:gravity="center"android:orientation="horizontal"></LinearLayout><LinearLayoutandroid:id="@+id/hw"android:layout_width="300dp"android:layout_height="500dp"android:layout_gravity="center"android:gravity="center"android:orientation="horizontal"></LinearLayout><TextViewandroid:id="@+id/txt_result"android:layout_gravity="center"android:layout_marginTop="@dimen/space"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="@dimen/txt_choose"android:textColor="@color/black"></TextView><LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:layout_marginBottom="100dp"android:gravity="center"android:orientation="horizontal"><LinearLayoutandroid:layout_width="@dimen/icon_loc"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><Buttonandroid:id="@+id/icon_lasso"android:layout_width="@dimen/icon_size"android:layout_height="@dimen/icon_size"android:background="@drawable/ic_lasso"></Button><TextViewandroid:id="@+id/txt_lasso"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/space"android:text="@string/txt_lasso"android:textColor="@color/black"android:textSize="@dimen/btn_txt_size"></TextView></LinearLayout><LinearLayoutandroid:layout_width="@dimen/icon_loc"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><Buttonandroid:id="@+id/icon_pen"android:layout_width="@dimen/icon_size"android:layout_height="@dimen/icon_size"android:background="@drawable/ic_pen"></Button><TextViewandroid:id="@+id/txt_pen"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/space"android:text="@string/txt_pen"android:textColor="@color/black"android:textSize="@dimen/btn_txt_size"></TextView></LinearLayout><LinearLayoutandroid:layout_width="@dimen/icon_loc"android:layout_height="match_parent"android:gravity="center"android:orientation="vertical"><Buttonandroid:id="@+id/icon_next"android:layout_width="@dimen/icon_size"android:layout_height="@dimen/icon_size"android:gravity="center"android:background="@drawable/ic_next"></Button><TextViewandroid:id="@+id/txt_next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="@dimen/space"android:text="@string/txt_next"android:textColor="@color/black"android:textSize="@dimen/btn_txt_size"></TextView></LinearLayout></LinearLayout>
</LinearLayout>

2.file_paths.xml图片存储路径

<?xml version="1.0" encoding="utf-8"?>
<resources><external-cache-path path="." name="take_photo"/>
</resources>

3.mainfest文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.buildmaterialapplication"><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"tools:ignore="ProtectedPermissions"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.CAMERA"/><uses-permission android:name="android.permission.INTERNET" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_car"android:label="@string/app_name"android:roundIcon="@drawable/ic_car"android:supportsRtl="true"android:theme="@style/Theme.MyApplication"android:requestLegacyExternalStorage="true"android:usesCleartextTraffic="true"android:hardwareAccelerated="false"android:largeHeap="true"><activityandroid:name=".MainActivity"android:exported="true"tools:ignore="DuplicateActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><providerandroid:authorities="com.buildmaterialapplication.fileprovider"android:name="androidx.core.content.FileProvider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths"/></provider></application><supports-screens android:resizeable="true" />
</manifest>

4.MainActivity

package com.buildmaterialapplication;import android.Manifest;
import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;import org.jetbrains.annotations.Nullable;
import org.opencv.core.Mat;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.FileProvider;//阅读前请查看README文件
public class MainActivity extends AppCompatActivity {//spinner用的列表private final static String[] items = new String[]{"拍照","从相册中选择",};public static final int TAKE_PHOTO=1;//声明一个请求码,用于识别返回的结果private static final int SCAN_OPEN_PHONE = 2;// 相册private Uri imageUri;public String path=null;Bitmap bitmap=null;public int count=0;public String picpath=null;private LinearLayout handWrite=null;public HandWrite hd;public HandWrite ori_hd;    //当前显示的handwrite控件public boolean isLasso=false;   //是否选择范围int requestW=0;         //初始化页面显示的图片的宽高int requestH=0;int drawType=0;         //画笔类型 1画笔 2橡皮 3套索@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);askPermission();//用于设置图片显示的大小DisplayMetrics dm=getResources().getDisplayMetrics();requestW=(int) (dm.widthPixels*0.8);requestH=(int) (dm.heightPixels*0.6);//加载手写类控件handWrite=findViewById(R.id.hw);choosePic();//aiAlgorithmbuttonEvent();if(drawType==0){TextView txt_pen=findViewById(R.id.txt_pen);txt_pen.setTextColor(Color.BLACK);}}/*** @name: askPermission* @param :null* @return :null* @describe:  请求相机等权限*/private void askPermission(){ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA},0);}/*** @name: buttonEvent* @param :null* @return null* @describe:  按钮点击事件*/public void buttonEvent() {Button btn_pen;Button btn_lasso;Button btn_eraser;TextView txt_pen = findViewById(R.id.txt_pen);TextView txt_lasso = findViewById(R.id.txt_lasso);btn_pen = (Button) findViewById(R.id.icon_pen);//画笔事件btn_pen.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {txt_pen.setTextColor(Color.GRAY);txt_lasso.setTextColor(Color.BLACK);drawType = 1;ori_hd.setPen_type(drawType);}});//套索事件btn_lasso = (Button) findViewById(R.id.icon_lasso);btn_lasso.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {txt_lasso.setTextColor(Color.GRAY);txt_pen.setTextColor(Color.BLACK);
//                draw_type=0;drawType = 3;ori_hd.setPen_type(drawType);isLasso = true;}});//下一张Button ic_next = (Button) findViewById(R.id.icon_next);ic_next.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(com.buildmaterialapplication.MainActivity.this, com.buildmaterialapplication.MainActivity.class));}});}/*** @name: choosePic* @params:* @return* @describe:  选择照片或拍照*/private void choosePic(){count=0;AlertDialog.Builder builder = new AlertDialog.Builder(com.buildmaterialapplication.MainActivity.this).setTitle("请选择图片")//设置对话框 标题.setItems(items, new DialogInterface.OnClickListener() {@RequiresApi(api = Build.VERSION_CODES.N)@Overridepublic void onClick(DialogInterface dialog, int which) {if(which==0){openCamera();}else{openGallery();}return;}});builder.create().show();}/*** @name: openGallery* @params:* @return* @describe:  拍照*/private void openGallery() {Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);//intent.setType("image/*");startActivityForResult(intent, SCAN_OPEN_PHONE);}/*** @name: openCamera* @params:* @return* @describe:  拍照*/@RequiresApi(api = Build.VERSION_CODES.N)private void openCamera(){String imageName = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(new Date());
//        File outputImage=new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/data/com.example.woundapplication/"+imageName+".jpg");File outputImage = new File(getExternalCacheDir(), imageName+".jpg");Objects.requireNonNull(outputImage.getParentFile()).mkdirs();
//        Log.e("", outputImage.getAbsolutePath());/*创建一个File文件对象,用于存放摄像头拍下的图片,我们把这个图片命名为output_image.jpg并把它存放在应用关联缓存目录下,调用getExternalCacheDir()可以得到这个目录,为什么要用关联缓存目录呢?由于android6.0开始,读写sd卡列为了危险权限,使用的时候必须要有权限,应用关联目录则可以跳过这一步*/try//判断图片是否存在,存在则删除在创建,不存在则直接创建{if(outputImage.exists()){outputImage.delete();}boolean a = outputImage.createNewFile();
//            Log.e("createNewFile", String.valueOf(a));}catch (IOException e){e.printStackTrace();}if(Build.VERSION.SDK_INT>=24)//判断安卓的版本是否高于7.0,高于则调用高于的方法,低于则调用低于的方法//把文件转换成Uri对象/*之所以这样,是因为android7.0以后直接使用本地真实路径是不安全的,会抛出异常。FileProvider是一种特殊的内容提供器,可以对数据进行保护*/{imageUri= FileProvider.getUriForFile(com.buildmaterialapplication.MainActivity.this,"com.buildmaterialapplication.fileprovider",outputImage);
//            imageUri=Uri.fromFile(outputImage);path=imageUri.getPath();Log.e(">7:",path);/*第一个参数:context对象第二个参数:任意唯一的字符串第三个参数:文件对象*/}else {imageUri= Uri.fromFile(outputImage);path=imageUri.getPath();Log.e("<7:",imageUri.getPath());}//使用隐示的Intent,系统会找到与它对应的活动,即调用摄像头,并把它存储Intent intent0=new Intent("android.media.action.IMAGE_CAPTURE");
//        Intent intent0=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);intent0.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);startActivityForResult(intent0,TAKE_PHOTO);//调用会返回结果的开启方式,返回成功的话,则把它显示出来Log.e("pic",path);}//拍照或相册的响应事件@SuppressLint("SetTextI18n")protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);Bitmap bitmaptmp;switch (requestCode) {case TAKE_PHOTO:if (resultCode == RESULT_OK) {//将图片解析成Bitmap对象,并把它显现出来try {bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));} catch (FileNotFoundException e) {e.printStackTrace();}picpath= com.buildmaterialapplication.MainActivity.this.getExternalCacheDir().getPath()+imageUri.getPath();
//                        bitmap =BitmapFactory.decodeStream(filePath);Log.e("filename",picpath);@SuppressLint("SdCardPath") String fileName = picpath;//缩放bitmap=getScaleBitmap(bitmap,requestW,requestH);Mat m=new Mat();hd=new HandWrite(com.buildmaterialapplication.MainActivity.this,bitmap,0);handWrite.addView(hd);ori_hd=hd;}break;//相册的响应case SCAN_OPEN_PHONE:if (resultCode == RESULT_OK){Uri selectImage=data.getData();String[] FilePathColumn={MediaStore.Images.Media.DATA};Cursor cursor = getContentResolver().query(selectImage,FilePathColumn, null, null, null);cursor.moveToFirst();//从数据视图中获取已选择图片的路径int columnIndex = cursor.getColumnIndex(FilePathColumn[0]);picpath = cursor.getString(columnIndex);Log.e("picpath",picpath);cursor.close();bitmaptmp=BitmapFactory.decodeFile(picpath);bitmap=getScaleBitmap(bitmaptmp,requestW,requestH);//预处理hd=new HandWrite(com.buildmaterialapplication.MainActivity.this,bitmap,0);handWrite.addView(hd);ori_hd=hd;}break;default:break;}}/*** @name: getScaleBitmap* @params:*      sourceBitmap:原图*      width: 需要的宽*      height: 需要的高* @return* @describe:  bitmap缩放函数*/private Bitmap getScaleBitmap(Bitmap sourceBitmap,float width,float height){Bitmap scaleBitmap;Matrix matrix = new Matrix();float scale= 0;if(sourceBitmap.getWidth()>sourceBitmap.getHeight()){scale=width/sourceBitmap.getWidth();}else{scale=height/ sourceBitmap.getHeight();}
//        float scale_x = width/sourceBitmap.getWidth();
//        float scale_y = height/sourceBitmap.getHeight();matrix.postScale(scale,scale);try {scaleBitmap = Bitmap.createBitmap(sourceBitmap,0,0,sourceBitmap.getWidth(),sourceBitmap.getHeight(),matrix,true);}catch (OutOfMemoryError e){scaleBitmap = null;System.gc();}return scaleBitmap;}
}

结语

最后只保留了涂鸦的部分,擦除有点bug
不想读取手机中的照片,想直接用电脑上的照片的话,改掉handwrite类里的构造方法就好了,注释中有写使用本地资源的方法,
代码还是有很多问题的,handwrite类的刷新写的也很麻烦,如果不是学习Android的话,尽量不要用这么底层的方法去写

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/27861.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

仿微信图片编辑软件,涂鸦、裁剪、添加文本等常规操作

1、需求 在做一个野外地质数据采集软件开发的过程中&#xff0c;有时候需要进行拍照保存&#xff0c;在此&#xff0c;我们直接通过Intent调用系统的拍照功能&#xff1b;然后&#xff0c;调用系统的裁剪功能&#xff0c;可以按照需要的大小进行裁剪&#xff1b;但是但是但是。…

iOS 图片涂鸦功能

大致原理&#xff1a; 1.准备几张切图。 2.监听手势&#xff0c;手势开始&#xff0c;随机添加一张图片&#xff1b;手势移动&#xff0c;累加手势距离&#xff0c;到达一定值再添加一张随机图片并清零累加距离&#xff0c;依次类推。 demo地址&#xff1a;https://github.co…

抖音私信名片_抖音消息卡片_抖音跳转微信_抖音私信跳转_抖音落地页

近期见到许多人到求这一的信息卡片个人名片是怎么做的&#xff0c;我四处请人了解&#xff0c;总算找到这一卡片的做法。 这个是抖音内置的作用&#xff0c;它是抖音橱窗的一个作用&#xff0c;沒有开通抖音橱窗是完成不上这一作用的&#xff0c;得下开通橱窗作用&#xff0c;…

AI辅助编程,GitHub copilot chat 体验

最近&#xff0c;看到很多大佬分享 GitHub copilot chat &#xff0c;据说能够让效率翻倍&#xff0c;抱着不相信&#xff0c;打假的心态我也弄一个&#xff0c;体验一下&#xff0c;结果真的很赞&#xff0c;下面分享使用 GitHub copilot chat 的过程 ​ 首先&#xff0c;我们…

工作完三年后,分享分享Java后端开发的一些心得

今年进入我工作的第四个年头, 三年多的时间里, 算上实习, 经历过3家公司. 见过了各种各样的同事, 也算见过各式各样的代码. 这篇文章主要是想分享一下一个java后端三年的一些感悟, 关于编程上的, 工作上的, 和同事相处上的. 一: 关于开发 我把关于编程的写在最前面, 我觉得对于…

打工人都在用的AI工具(第二期)

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

一人改代码搞崩推特,马斯克气疯:全部重写!

鱼羊 丰色 发自 凹非寺量子位 | 公众号 QbitAI “马斯克气疯了”&#xff01; 就在今天&#xff0c;推特又双叒崩溃了&#xff0c;图片和任何链接都打不开。 据马斯克自己的说法&#xff0c;原因只是“API的一个小改动”。 但后果很严重&#xff0c;起码在网友们看来&#xff0…

【真北直播笔记】董越:简明DevOps学习地图

缘起 真北敏捷社区的宗旨是&#xff1a;求知、连接。求知就是学习&#xff0c;家里没矿的话&#xff0c;学习是一个人最重要的动力之源。连接就是把人拉在一起&#xff0c;我们相信人与人的互动会带来美好的变化。今天的直播是把大家拉在一起学习&#xff0c;就是求知、连接。 …

云原生可观测领域的半壁江山,这次被 Grafana 和 Cilium 给拿下了

两个多月前&#xff0c;Grafana 实验室宣布与 Cilium 母公司 Isovalent 建立战略合作伙伴关系[1]&#xff0c;希望通过 Grafana 开源的可观测性全家桶组件&#xff0c;帮助各个基础架构团队深度探测 Kubernetes 集群工作负载的安全、性能和相互之间的连接状况。在这之前&#x…

爽翻!Github Copilot X发布,集成了GPT-4,远不止帮写代码

点击上方“编程技术进阶”&#xff0c;加"星标" 重磅干货&#xff0c;第一时间送达 大家好&#xff0c;我是编哥。今天看到Github Copilot X发布&#xff0c;真的不只帮写代码&#xff0c;不信往下看。 Copilot X 的本事&#xff0c;当你选中一段代码&#xff0c;可以…

AI 告诉你 一行代码生成树形结构

一、前言 在我们日常开发中生成树形结构是无可避免的&#xff0c;比如权限管理的层级结构&#xff0c;学校企业的组织结构以及我们日常开发的菜单列表等等。我最近看到过一篇文章&#xff0c;在面试的过程中&#xff0c;会被要求手写一下如何根据扁平的数据结构生成一个树形结构…

巴比特 | 元宇宙每日必读:AI概念股集体大跌、光年之外卖给美团、ChatGPT也涨不动了,大模型热潮正在降温?创业者如何抉择?...

摘要&#xff1a;据甲子光年报道&#xff0c;在高喊“要做中国版OpenAI”之后的第136天&#xff0c;王慧文把光年之外卖给了美团。从整体商业视角看&#xff0c;光年之外被美团收购只是企业间常见的收购动作。但对于国内AI行业来说&#xff0c;这笔收购似乎预示着仅火热半年的A…

ChatGPT来了,全国百万打工人都慌了......

关注我们丨文末赠书 如果说上个月AIGC的热度还只停留在技术圈&#xff0c;那么最近AIGC的影响力已经辐射到普通打工人了&#xff01; 4月18日&#xff0c;国内办公软件巨头金山正式发布了生成式人工智能应用WPS AI&#xff0c;这也是国内协同办公赛道首个类ChatGPT式应用&#…

BSP按键适配

笔记目录 GPIO按键适配PS&#xff1a;每次修改适配都要再客制化一下,来更新修改。&#xff01;&#xff01;&#xff01;一、GPIO按键适配&#xff08;Rk&#xff09;linux键值二、GPIO适配&#xff1a;RK平台&#xff08;android11&#xff09;调试&#xff1a;1、adb命令打开…

ubuntu和ros安装后的初始化

huanyu机器人学习&#xff0c;要把代码学会 分区规则&#xff1a;以350G左右为例 找到空闲&#xff1a; ext4→efi 逻辑分区 1G ext4→交换空间 逻辑分区 30/32G&#xff08;按照内存选&#xff0c;16G用32&#xff09; 挂载点→ / → 主分区 →100G 挂载点→/usr → 逻辑分区…

AI小作文搞崩科大讯飞股价 科技“魔法”反噬科企

5月24日午后&#xff0c;A股公司科大讯飞的股价突然走出深V造型&#xff0c;闪崩8%。科大讯飞回应称&#xff0c;股价下跌系某生成式AI写作虚假小作文导致&#xff0c;谣传风险为不实消息。 网传的一篇“小作文”谣称“科大讯飞被曝采集用户隐私数据研究人工智能引发争议”&am…

1月安全月报 | 2亿Twitter用户数据被公开;美计划发起“黑掉五角大楼3.0”漏洞赏金计划

目录 国外安全热点 &#x1f449;安全政策 &#x1f449;数据安全 &#x1f449;市场趋势 &#x1f449;勒索事件 国内安全热点 &#x1f449;数据安全 &#x1f449;业务安全 &#x1f449;移动安全 &#x1f449;网安政策 为了让大家更全面的了解网络安全的风险&am…

上下文工程:基于 Github Copilot 的实时能力分析与思考

上个月在计划为 AutoDev 添加多语言支持时候&#xff0c;发现 GitHub Copilot 的插件功能是语言无关的&#xff08;通过 plugin.xml 分析&#xff09;&#xff0c;便想研究一下它是如何使用 TreeSitter 的。可惜的是&#xff0c;直到最近才有空&#xff0c;研究一下它是如何实现…

零门槛复现ChatGPT:预训练模型数据集直接用,包含完整RLHF流程,在线可体验...

明敏 发自 凹非寺量子位 | 公众号 QbitAI 这边ChatGPT、GPT-4等AI大模型和应用打得火热&#xff1b; 另一边“平替”开源复现方案也加紧更新迭代。 这不&#xff0c;“首个开源ChatGPT低成本复现流程”就来了波大更新&#xff01; 现在&#xff0c;仅需不到百亿参数&#xff0c…

面试的三种形式

对于面试大家都不会陌生&#xff0c;大大小小的面试也都经历过&#xff0c;有过不是很正规的&#xff0c;也有过让自己大开眼界的大型面试&#xff0c;但无外乎三种形式电话面试&#xff0c;共享桌面远程面试&#xff0c;现场面试。但是在这几种面试的场合中&#xff0c;我们到…