智能无人机平台V4

V3版本回顾

在V3版本中,实现了无人机的自动索敌追踪、并在扫描到入侵者后将信息“广播”给其他无人机,其他巡逻状态的无人机可以协同该无人机进行“围剿”行为。

V4版本提升

  • 为入侵者加入了可视化的血条,便于玩家更直观的看到入侵者血量减少的过程
  • 加入了“任务系统”,现在玩家可以通过点击守卫区中的位置来指挥最近的巡逻状态无人机前往该位置
  • 将无人机的move方法内部的庞大代码分成几个小的方法,并通过不同的限定条件来调用不同的方法。同时为了便于后期功能的添加,现在将无人机移动方案的限定条件改为由状态码的不同来决定无人机的移动方式。

V4版本的具体实现

可视化血条的添加

  • 思路:只需要在入侵者的正上方画出一个矩形边框和一个实心矩形即可,通过改变实心矩形的宽度来达到显示血量的效果

具体实现

Color color3 =newColor(0,0,0); g.setColor(color3); g.drawRect(x, y-5, size,6);Color color4 =newColor(124,244,21); g.setColor(color4); g.fillRect(x+1,y-4,(int)(blood/200.0*(size-1)),5);

任务系统的添加

  • 思路及代码:

在上个版本中,无人机的move方法过于庞大且判定条件没有统一化,导致后续再添加其他功能时非常麻烦,在V4版本中我改进了move方法,让move方法通过状态码来调用对应的移动方法来完成操作。代码实现如下

publicvoidmove(){if(state ==2){moveToTask();}elseif(state ==1){//先判断目标是否在守卫区外,若在守卫区外则不在追逐if(target!=null){if(target.x+target.size/2<200||target.x+target.size/2>900||target.y+target.size/2<100||target.y+target.size/2>600){ state=0; target=null;}else{moveToHunt();}}else{ state=0;}}elseif(state ==0){moveToFind();}}publicvoidmoveToTask(){int dx = targetTask.x+targetTask.size/2-(x+scanSize/2);int dy = targetTask.y+targetTask.size/2-(y+scanSize/2);double distance =Math.sqrt(dx*dx+dy*dy);if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed);}else{ huntingSpeedx=0; huntingSpeedy=0;System.out.println("完成任务"); state=0;//完成任务 targetTask.state=2; targetTask=null;//任务完成后清除任务目标}//硬限位,防止出界limit();}publicvoidmoveToHunt(){int dx = target.x+target.size/2-(x+scanSize/2);int dy = target.y+target.size/2-(y+scanSize/2);double distance =Math.sqrt(dx*dx+dy*dy);if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed);}else{ huntingSpeedx=0; huntingSpeedy=0;}//硬限位,防止出界limit();}publicvoidmoveToFind(){ x += speedx; y += speedy;if(x <200|| x >900){ speedx =-speedx;}if(y <100|| y >600){ speedy =-speedy;}}publicvoidlimit(){int newx = x+huntingSpeedx;int newy = y+huntingSpeedy; x =Math.max(200,Math.min(1000- scanSize, newx)); y =Math.max(100,Math.min(700- scanSize, newy));}

在Drone类中构建moveToTask方法,让最近的无人机在接到任务后计算速度并前往,逻辑与追踪入侵者类似,并在无人机中心与任务点距离小于20时,将状态设置为任务完成,并清空任务目标。代码实现如下

publicvoidmoveToTask(){int dx = targetTask.x+targetTask.size/2-(x+scanSize/2);int dy = targetTask.y+targetTask.size/2-(y+scanSize/2);double distance =Math.sqrt(dx*dx+dy*dy);if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed);}else{ huntingSpeedx=0; huntingSpeedy=0;System.out.println("完成任务"); state=0;//完成任务 targetTask.state=2; targetTask=null;//任务完成后清除任务目标}//硬限位,防止出界int newx = x+huntingSpeedx;int newy = y+huntingSpeedy; x =Math.max(200,Math.min(1000- scanSize, newx)); y =Math.max(100,Math.min(700- scanSize, newy));}

无人机move方法的优化

在DroneThread线程中画出任务点,若任务完成,则移除任务对象且不进行绘制。具体代码实现如下

if(tasks !=null){for(int i =0; i < tasks.size(); i++){Task task = tasks.get(i);if(task.state==2){ tasks.remove(i);}else{ task.draw(bg);}}}

创建任务线程类TaskThread,在类中重写run方法。在run方法中遍历无人机与任务数组,将未被分配的任务分配给距离最近且处于巡逻状态的无人机,任务被分配后将任务的状态设置为已被领取,若此时没有空闲的无人机,则输出“没有可指挥的无人机”来提示玩家。代码实现如下

packagecom.nwu.by0129.droneV4;importjava.util.ArrayList;publicclassTaskThreadextendsThread{ArrayList<Task> tasks;ArrayList<Drone> drones;@Overridepublicvoidrun(){for(;;){//System.out.println("进入TaskThread");if(tasks !=null){if(drones !=null){for(int i = tasks.size()-1; i >=0; i--){Task task = tasks.get(i);if(task.state !=1){int nearestIndex =-1;double minDis =1000.0;for(int j = drones.size()-1; j >=0; j--){Drone drone = drones.get(j);//找到没有领取任务的无人机(只有巡逻状态的无人机可以接任务)if(drone.state ==0){//计算距离并找出最近的double currentDis =caculateDis(task, drone);if(currentDis <= minDis){ minDis = currentDis; nearestIndex = j;//把最近的无人机编号取出来}}}if(nearestIndex !=-1){ drones.get(nearestIndex).state =2;//无人机状态设为正在执行任务 drones.get(nearestIndex).targetTask = task;System.out.println("任务被领取"); task.state =1;//任务状态设为已被领取}else{System.out.println("没有可指挥的无人机"); task.state =0;}}}}}try{Thread.sleep(16);}catch(InterruptedException e){thrownewRuntimeException(e);}}}doublecaculateDis(Task task,Drone drone){double dis =Math.sqrt((task.x - drone.x)*(task.x - drone.x)+(task.y - drone.y)*(task.y - drone.y)*1.0);return dis;}}

创建鼠标监听器,并在DroneListener类中加入鼠标监听器的相关内容。重写mousePressed方法,将鼠标点击的坐标作为参数构建task对象,使用共享内存的思路,并存入tasks动态数组,便于其他无人机领取任务。代码实现如下

publicvoidmousePressed(MouseEvent e){int x=e.getX();int y=e.getY();Task task =newTask(0,x,y);//对任务点进行判断,不得超出守卫区的范围if(!(task.x<200+ task.size/2+50||task.x>1000- task.size/2-50||task.y<100+ task.size+50||task.y>700-task.size-50)){ tasks.add(task);}}

创建Task类,将玩家发布的任务封装起来,类中包括该任务点的坐标、状态属性以及可视化的绘制方法。代码实现如下

packagecom.nwu.by0129.droneV4;importjava.awt.*;publicclassTask{int x;int y;int size=10;int state;//0未被领取的任务;1被领取的任务;2已完成的任务publicTask(int state,int x,int y){this.state = state;this.x = x;this.y = y;}publicvoiddraw(Graphics g){ g.setColor(Color.yellow); g.fillRect(x-size/2,y-size/2,size,size);}}

V4版本完整代码如下

packagecom.nwu.by0129.droneV4;importjava.awt.*;importjava.awt.image.BufferedImage;publicclassDrone{int x;int y;int stateSize =16;int scanSize =100;int size =30;int state =0;// 0巡逻中;1追踪中;2执行任务中int speedx;int speedy;int huntingSpeedx;int huntingSpeedy;int rSquare=scanSize*scanSize/4;int huntingSpeed =4;//设置追逐速度Intruder target =null;Task targetTask =null;publicDrone(int x,int y,int speedx,int speedy){this.x = x;this.y = y;this.speedx = speedx;this.speedy = speedy;}publicvoiddrawDrone(Graphics g){Color color1 =newColor(52,146,241,75); g.setColor(color1); g.fillOval(x, y, scanSize, scanSize);Color color2 =newColor(111,200,34); g.setColor(color2); g.fillOval(x +35, y +35, size, size);Color color3 =newColor(243,82,82);if(state ==0){ g.setColor(color3); g.fillOval(x +42, y +42, stateSize, stateSize);}elseif(state ==1||state ==2){Color color4 =newColor(5,25,246); g.setColor(color4); g.fillOval(x +42, y +42, stateSize, stateSize);}}publicvoidmove(){if(state ==2){moveToTask();}elseif(state ==1){//先判断目标是否在守卫区外,若在守卫区外则不在追逐if(target!=null){if(target.x+target.size/2<200||target.x+target.size/2>900||target.y+target.size/2<100||target.y+target.size/2>600){ state=0; target=null;}else{moveToHunt();}}else{ state=0;}}elseif(state ==0){moveToFind();}}publicScanResultscan(int x,int y,int size,BufferedImage img){int distanceSquare;for(int i = x; i < x + size; i++){for(int j = y; j < y + size; j++){int roundx=x + scanSize /2;int roundy=y + scanSize /2; distanceSquare =(roundx - i)*(roundx - i)+(roundy - j)*(roundy - j);if(distanceSquare < rSquare){try{int colorNum = img.getRGB(i,j);Color color =newColor(colorNum);Color targetColor1 =newColor(213,15,15);Color targetColor2 =newColor(0,0,0);if(isIntruderColor(color,targetColor1,25)||isIntruderColor(color,targetColor2,30)){//System.out.println("扫描到入侵者");ScanResult sr=newScanResult(i,j);return sr ;}}catch(Exception e){// 处理超出图像范围的情况continue;}}}}returnnull;}//颜色判断方法publicboolean isIntruderColor (Color c1,Color c2,int tolerance){returnMath.abs(c1.getRed()-c2.getRed())<= tolerance &&Math.abs(c1.getGreen()-c2.getGreen())<= tolerance &&Math.abs(c1.getBlue()-c2.getBlue())<= tolerance;}publicvoidmoveToTask(){int dx = targetTask.x+targetTask.size/2-(x+scanSize/2);int dy = targetTask.y+targetTask.size/2-(y+scanSize/2);double distance =Math.sqrt(dx*dx+dy*dy);if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed);}else{ huntingSpeedx=0; huntingSpeedy=0;System.out.println("完成任务"); state=0;//完成任务 targetTask.state=2; targetTask=null;//任务完成后清除任务目标}//硬限位,防止出界limit();}publicvoidmoveToHunt(){int dx = target.x+target.size/2-(x+scanSize/2);int dy = target.y+target.size/2-(y+scanSize/2);double distance =Math.sqrt(dx*dx+dy*dy);if(distance>20){ huntingSpeedx=(int)(dx/distance*huntingSpeed); huntingSpeedy=(int)(dy/distance*huntingSpeed);}else{ huntingSpeedx=0; huntingSpeedy=0;}//硬限位,防止出界limit();}publicvoidmoveToFind(){ x += speedx; y += speedy;if(x <200|| x >900){ speedx =-speedx;}if(y <100|| y >600){ speedy =-speedy;}}publicvoidlimit(){int newx = x+huntingSpeedx;int newy = y+huntingSpeedy; x =Math.max(200,Math.min(1000- scanSize, newx)); y =Math.max(100,Math.min(700- scanSize, newy));}}
packagecom.nwu.by0129.droneV4;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.awt.event.MouseEvent;importjava.awt.event.MouseListener;importjava.util.ArrayList;importjava.util.Random;publicclassDroneListenerimplementsActionListener,MouseListener{Random rand =newRandom();ArrayList<Drone> drones;ArrayList<Intruder> intruders;ArrayList<Task> tasks ;@OverridepublicvoidactionPerformed(ActionEvent e){if(e.getActionCommand().equals("生产无人机")){int x = rand.nextInt(700)+200;int y = rand.nextInt(500)+100;int speedx = rand.nextInt(5)-2;while(speedx==0){ speedx = rand.nextInt(5)-2;}int speedy = rand.nextInt(5)-2;while(speedy==0){ speedy = rand.nextInt(5)-2;}Drone drone =newDrone(x,y,speedx,speedy); drones.add(drone);}elseif(e.getActionCommand().equals("生产入侵者")){int x = rand.nextInt(1160);int y = rand.nextInt(760);while(true){if(y<60||y>700||x<160||x>1000){break;} x = rand.nextInt(1160); y = rand.nextInt(760);}int speedx = rand.nextInt(5)-2;while(speedx==0){ speedx = rand.nextInt(5)-2;}int speedy = rand.nextInt(5)-2;while(speedy==0){ speedy = rand.nextInt(5)-2;}Intruder intruder =newIntruder(x,y,speedx,speedy); intruders.add(intruder);}}@OverridepublicvoidmouseClicked(MouseEvent e){}@OverridepublicvoidmousePressed(MouseEvent e){int x=e.getX();int y=e.getY();Task task =newTask(0,x,y);//对任务点进行判断if(!(task.x<200+ task.size/2+50||task.x>1000- task.size/2-50||task.y<100+ task.size+50||task.y>700-task.size-50)){ tasks.add(task);}/*for (int i = 0; i < tasks.size(); i++) { System.out.println(tasks.get(i).x); }*///System.out.println(tasks.size());//System.out.println("task添加了");}@OverridepublicvoidmouseReleased(MouseEvent e){}@OverridepublicvoidmouseEntered(MouseEvent e){}@OverridepublicvoidmouseExited(MouseEvent e){}}
packagecom.nwu.by0129.droneV4;importjava.awt.*;importjava.awt.image.BufferedImage;importjava.util.ArrayList;publicclassDroneThreadextendsThread{Graphics g;ArrayList<Drone> drones;ArrayList<Intruder> intruders;ArrayList<Intruder> foundedIntruders =newArrayList<>();//将所有被扫描到的入侵者存入这里ArrayList<Task> tasks;publicDroneThread(Graphics g){this.g = g;}@Overridepublicvoidrun(){for(;;){BufferedImage image =newBufferedImage(1200,800,2);Graphics bg = image.getGraphics(); bg.setColor(Color.white); bg.fillRect(0,0,1200,800); bg.setColor(Color.red); bg.drawRect(200,100,800,600);if(drones !=null){for(int i =0; i < drones.size(); i++){Drone drone = drones.get(i); drone.drawDrone(bg); drone.move();}}if(intruders !=null){for(int i =0; i < intruders.size(); i++){Intruder intruder = intruders.get(i); intruder.drawIntruder(bg); intruder.move();}}//在这里用bg画笔画出任务点if(tasks !=null){//System.out.println("进入if");for(int i =0; i < tasks.size(); i++){Task task = tasks.get(i);if(task.state==2){ tasks.remove(i);}else{ task.draw(bg);}}}if(drones.size()>0){for(int k =0; k < drones.size(); k++){Drone drone = drones.get(k);ScanResult sr = drone.scan(drone.x, drone.y, drone.scanSize, image);if(sr !=null){//如果扫到目标if(drone.state==2){continue;//正在执行任务中就不处理入侵者}Intruder intruder =getTargetIntruder(sr.targetX, sr.targetY);//通过坐标把这个目标找出来if(intruder !=null){//找到目标后 drone.target = intruder;//把自己的目标设置为这个 drone.state =1; foundedIntruders.add(intruder);//把这个目标传入动态数组}}else{//如果没扫描到目标if(drone.state==0&& drone.target==null){if(foundedIntruders !=null){//看看动态数组里面有没有别人发现的目标for(int i = foundedIntruders.size()-1; i >=0; i--){Intruder intruder = foundedIntruders.get(i);if(intruder !=null){if(intruder.blood <=0||!isInRange(intruder)){//先判断这个目标还是否存在或在范围内 foundedIntruders.remove(i);//删掉死亡的或者逃跑的}else{ drone.target = intruder;//把自己的目标设置成这个目标 drone.state =1;}}}}}}}}if(intruders.size()>0){//如果该入侵者被某个无人机列为目标,就进行扣血for(int k =0; k < intruders.size(); k++){Intruder intruder = intruders.get(k);for(int i =0; i < drones.size(); i++){if(intruder == drones.get(i).target){ intruder.underAttack();System.out.println("第"+ k +"个入侵者被扫到,血量剩余:"+ intruder.blood);if(intruder.blood <=0||!isInRange(intruder)){//消灭入侵者 intruders.remove(k);for(Drone drone : drones){if(drone.target == intruder){ drone.target =null;if(drone.state==1){ drone.state =0;}}}}}}}} g.drawImage(image,0,0,null);try{Thread.sleep(16);}catch(InterruptedException e){thrownewRuntimeException(e);}}}publicIntrudergetTargetIntruder(int scannedI,int scannedJ){for(int k =0; k < intruders.size(); k++){Intruder intruder = intruders.get(k);int distanceSquare;for(int i = intruder.x; i < intruder.x + intruder.size; i++){for(int j = intruder.y; j < intruder.y + intruder.size; j++){int roundx = intruder.x + intruder.size /2;int roundy = intruder.y + intruder.size /2; distanceSquare =(roundx - i)*(roundx - i)+(roundy - j)*(roundy - j);if(distanceSquare < intruder.rSquare){if(i == scannedI && j == scannedJ){return intruder;}}}}}returnnull;}//判断入侵者是否在守卫区内publicbooleanisInRange(Intruder intruder){if(intruder.x <200+ intruder.size || intruder.x >1000- intruder.size || intruder.y <100+ intruder.size || intruder.y >700- intruder.size){returnfalse;}else{returntrue;}}}
packagecom.nwu.by0129.droneV4;importjavax.swing.*;importjava.awt.*;importjava.util.ArrayList;publicclassDroneUIextendsJFrame{ArrayList<Drone> drones=newArrayList<>();ArrayList<Intruder> intruders=newArrayList<>();ArrayList<Task> tasks=newArrayList<>();publicDroneUI(){setTitle("智能无人机平台4.0");setSize(1200,900);setDefaultCloseOperation(EXIT_ON_CLOSE);setLocationRelativeTo(null);JButton button1 =newJButton("生产无人机");JButton button2 =newJButton("生产入侵者");JPanel panel =newJPanel(); panel.setBackground(Color.lightGray); panel.add(button1); panel.add(button2);add(panel,BorderLayout.SOUTH);setVisible(true);Graphics g=this.getGraphics();//创建按钮监听器DroneListener droneListener =newDroneListener();//在创建监听器后立刻为集合赋值,让集合真正可用 droneListener.drones=drones; droneListener.intruders=intruders; droneListener.tasks=tasks; button1.addActionListener(droneListener); button2.addActionListener(droneListener);//创建鼠标监听器addMouseListener(droneListener);//创建无人机线程DroneThread droneThread =newDroneThread(g);//创建任务线程TaskThread taskThread =newTaskThread();//将共享内存的数组传入到两个线程中 droneThread.drones=drones; droneThread.intruders=intruders; droneThread.tasks=tasks;//要先将DroneUI类中的tasks传入给droneThread,这样才能在执行DroneThread的时候保证此时的tasks不是null taskThread.drones=drones; taskThread.tasks=tasks; droneThread.start(); taskThread.start();}@Overridepublicvoidpaint(Graphics g){super.paint(g);}publicstaticvoidmain(String[] args){newDroneUI();}}
packagecom.nwu.by0129.droneV4;importjava.awt.*;publicclassIntruder{int x;int y;int speedx;int speedy;int size=30;int blood=200;int rSquare=size*size/4;publicIntruder(int x,int y,int speedx,int speedy){this.x = x;this.y = y;this.speedx = speedx;this.speedy = speedy;}publicvoiddrawIntruder(Graphics g){if(blood>0){Color color1 =newColor(0,0,0); g.setColor(color1); g.fillOval(x, y, size, size);Color color2 =newColor(213,15,15); g.setColor(color2); g.fillOval(x+5, y+5, size-10, size-10);Color color3 =newColor(0,0,0); g.setColor(color3); g.drawRect(x, y-5, size,6);Color color4 =newColor(124,244,21); g.setColor(color4); g.fillRect(x+1,y-4,(int)(blood/200.0*(size-1)),5);}}publicvoidmove(){ x+=speedx; y+=speedy;if(x<=0||x>=1160){ speedx=-speedx;}if(y<=0||y>=760){ speedy=-speedy;}}publicvoidunderAttack(){this.blood--;}}
packagecom.nwu.by0129.droneV4;publicclassScanResult{int targetX;int targetY;publicScanResult(int targetX,int targetY){this.targetY = targetY;this.targetX = targetX;}}
packagecom.nwu.by0129.droneV4;importjava.awt.*;publicclassTask{int x;int y;int size=10;int state;//0未被领取的任务;1被领取的任务;2已完成的任务publicTask(int state,int x,int y){this.state = state;this.x = x;this.y = y;}publicvoiddraw(Graphics g){ g.setColor(Color.yellow); g.fillRect(x-size/2,y-size/2,size,size);}}
packagecom.nwu.by0129.droneV4;importjava.util.ArrayList;publicclassTaskThreadextendsThread{ArrayList<Task> tasks;ArrayList<Drone> drones;@Overridepublicvoidrun(){for(;;){//System.out.println("进入TaskThread");if(tasks !=null){if(drones !=null){for(int i = tasks.size()-1; i >=0; i--){Task task = tasks.get(i);if(task.state !=1){int nearestIndex =-1;double minDis =1000.0;for(int j = drones.size()-1; j >=0; j--){Drone drone = drones.get(j);//找到没有领取任务的无人机(只有巡逻状态的无人机可以接任务)if(drone.state ==0){//计算距离并找出最近的double currentDis =caculateDis(task, drone);if(currentDis <= minDis){ minDis = currentDis; nearestIndex = j;//把最近的无人机编号取出来}}}if(nearestIndex !=-1){ drones.get(nearestIndex).state =2;//无人机状态设为正在执行任务 drones.get(nearestIndex).targetTask = task;System.out.println("任务被领取"); task.state =1;//任务状态设为已被领取}else{System.out.println("没有可指挥的无人机"); task.state =0;}}}}}try{Thread.sleep(16);}catch(InterruptedException e){thrownewRuntimeException(e);}}}doublecaculateDis(Task task,Drone drone){double dis =Math.sqrt((task.x - drone.x)*(task.x - drone.x)+(task.y - drone.y)*(task.y - drone.y)*1.0);return dis;}}

运行结果截图及视频演示

运行截图

在这里插入图片描述
在这里插入图片描述
  1. 视频演示

智能无人机V4视频演示

总结

在本次V4版本的开发中,我加深了对于面向对象的理解,对于大部分重复的代码,我们可以通过一个方法来将其封装起来,重复调用即可;同时我也认识到了代码前期设计的重要性,前期的设计要规范化,要为之后的功能添加留出充足的拓展空间。

Read more

AI绘画神器Z-Image-Turbo:输入文字秒出图,艺术创作从未如此简单

AI绘画神器Z-Image-Turbo:输入文字秒出图,艺术创作从未如此简单 你有没有过这样的时刻:脑子里已经浮现出一张绝美的画面——晨雾中的山寺飞檐、赛博朋克街角的霓虹猫、水墨晕染的敦煌飞天——可当你打开绘图软件,却卡在第一步:怎么把脑海里的东西,变成屏幕上真实可感的图像? 不是不会画,是没时间学;不是不想试,是怕折腾半天只出一张糊图。更别提那些动辄要配3090显卡、等五分钟才出一张图的工具,还没开始创作,热情就被加载条浇灭了。 今天我要分享的,不是又一个“理论上很厉害”的模型,而是一个真正能让你合上笔记本、拿起手机、输入一句话、三秒后就看到高清大图的工具——Z-Image-Turbo 极速云端创作室。 它不教你怎么调参数,不让你研究CFG值和采样器区别,甚至不需要你记住任何英文术语。它只有一个按钮:“ 极速生成”。点下去,结果就来了。 这不是未来科技,是今天就能用上的现实。我用它给朋友做生日贺图,12秒生成一张带名字的星空手绘风插画;用它帮设计师同事赶海报初稿,输入“极简风咖啡馆LOGO,暖棕+米白,有手冲壶剪影”,第一张就通过了;甚至用它给孩子讲古诗,输入“

AI绘画提示词生成器:从原理到实战的开发者指南

快速体验 在开始今天关于 AI绘画提示词生成器:从原理到实战的开发者指南 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 AI绘画提示词生成器:从原理到实战的开发者指南 背景与痛点 AI绘画的兴起让提示词(Prompt)成为连接创意与生成结果的关键纽带。然而在实际开发中,构建一个高效的提示词生成器常面临以下挑战: * 质量不稳定:生成的提示词可能过于笼统(如"

Stable-Diffusion-v1-5-archive惊艳效果展示:35mm胶片风、赛博朋克、水墨国风案例

Stable-Diffusion-v1-5-archive惊艳效果展示:35mm胶片风、赛博朋克、水墨国风案例 很多人觉得Stable Diffusion 1.5已经是“老古董”了,跟不上现在各种新模型的花样。但说实话,经典之所以是经典,就是因为它足够稳定、可控,而且风格塑造能力极强。今天我就用 stable-diffusion-v1-5-archive 这个归档版本,给大家展示几个让我眼前一亮的生成效果,看看这个“老将”在特定风格下,能玩出什么新花样。 我们重点看三个风格:充满故事感的35mm胶片风、未来感爆棚的赛博朋克、以及意境深远的水墨国风。我会把生成这些图的提示词、参数设置都贴出来,你可以直接拿去用,看看能不能复现出同样惊艳的效果。 1. 核心能力与准备工作 在开始展示之前,我们先快速了解一下这个镜像能做什么,以及怎么快速上手。 1.1 它能做什么? Stable Diffusion v1.5 Archive 是一个开箱即用的经典文生图模型。它的核心就是:你输入一段文字描述,它给你生成一张对应的图片。别看它版本老,

基于FPGA的千兆以太网源代码实现与设计实战

本文还有配套的精品资源,点击获取 简介:本设计基于FPGA平台,实现千兆以太网的数据传输功能,适用于高速网络通信场景,如视频信号的高效传输。通过Verilog等硬件描述语言,构建包括以太网物理层(PHY)、MAC控制器、Wishbone总线接口等核心模块,并提供完整的测试平台与行为模型用于仿真验证。配套的使用说明指导开发者在特定FPGA平台上配置和部署该系统,具有较强的工程实用性。该方案广泛应用于嵌入式系统、工业控制和高性能数据传输领域,是掌握FPGA网络接口开发的重要实践项目。 1. FPGA千兆以太网设计概述 随着高速通信需求的不断增长,基于FPGA实现千兆以太网接口已成为嵌入式系统、工业控制和视频传输等领域的重要技术手段。本章从系统架构出发,阐述FPGA在千兆以太网设计中的核心优势——强大的并行处理能力、灵活的可重构性以及极低的数据处理延迟。重点介绍关键功能模块的划分与协作机制,包括PHY层接口、MAC控制器、Wishbone总线桥接及数据包处理引擎,并结合IEEE 802.3标准解析千兆以太网帧结构与物理层规范。同时,明确顶层模块( eth_top )的数据流向与控制