程序员之电工基础-CV程序解决目标检测

一、背景

        兴趣爱好来了,决定研发一个产品。涉及到电工和机械等知识,所以记录一下相关的基础知识。今天的内容又回到了我的主营板块!!哈哈!!为后续整体集成做准备,先测试目标检测部分的能力。

二、需求描述

       我的需求是流水线上的工业相机拍摄不同产品的图片,同批次生产产品的第1个,需要设别特征或者某个标识物,把标识物设定为标识物模版。后面,同批次生产产品来到这个作业环节的时候,我们从新拍的图片中找到标识物模板所处位置就成功啦!!!

        我期望是自动寻找标识物,人工可以选择自动寻找的标识物,也可以手工选择标识物。

三、完整代码

        1.开发环境搭建

        就不多说了,参考我之前的文章工业生产安全-安全帽第一篇-opencv及java开发环境搭建_安全帽识别Java开发入门-CSDN博客

        2.标识模版制作程序

        (1)功能代码MarkerDetector.java        

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;public class MarkerDetector {// 加载OpenCV库(需提前配置)static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);}// 标识物筛选参数(可配置)private static final int MIN_AREA = 100;       // 最小面积(像素)private static final int MAX_AREA = 5000;     // 最大面积(像素)private static final double MIN_ASPECT_RATIO = 0.3;  // 最小宽高比private static final double MAX_ASPECT_RATIO = 3.0;  // 最大宽高比// 检测到的标识物列表private List<Marker> detectedMarkers = new ArrayList<>();// 选中的标识物模板private Marker selectedMarker;String templateRootPath="d:/test/";/*** 从拼接图像中自动检测标识物* @param stitchedImagePath 拼接后的图像路径* @return 排序后的前3个标识物*/public List<Marker> autoDetectMarkers(String stitchedImagePath) {// 1. 读取图像并预处理Mat image = Imgcodecs.imread(stitchedImagePath);if (image.empty()) {throw new RuntimeException("无法读取图像: " + stitchedImagePath);}// 灰度化→降噪→二值化Mat gray = new Mat();Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);Mat blurred = new Mat();Imgproc.GaussianBlur(gray, blurred, new Size(5, 5), 0);Mat thresh = new Mat();Imgproc.threshold(blurred, thresh, 0, 255, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU);// 2. 轮廓检测List<MatOfPoint> contours = new ArrayList<>();Mat hierarchy = new Mat();Imgproc.findContours(thresh.clone(), contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);// 3. 筛选符合条件的轮廓(作为候选标识物)for (MatOfPoint contour : contours) {// 计算轮廓面积double area = Imgproc.contourArea(contour);if (area < MIN_AREA || area > MAX_AREA) {continue;}// 计算边界框Rect rect = Imgproc.boundingRect(contour);double aspectRatio = (double) rect.width / rect.height;if (aspectRatio < MIN_ASPECT_RATIO || aspectRatio > MAX_ASPECT_RATIO) {continue;}// 计算轮廓复杂度(形状越规则,越可能是标识物)MatOfPoint2f contour2f = new MatOfPoint2f(contour.toArray());double perimeter = Imgproc.arcLength(contour2f, true);MatOfPoint2f approx = new MatOfPoint2f();Imgproc.approxPolyDP(contour2f, approx, 0.02 * perimeter, true);int vertices = approx.toArray().length;// 保存标识物信息(按"面积+规则度"排序)Marker marker = new Marker(rect, area, vertices, image.submat(rect));detectedMarkers.add(marker);}// 4. 按优先级排序(面积大的优先,形状规则的优先)detectedMarkers.sort(Comparator.comparingDouble(Marker::getPriority).reversed());// 返回前3个标识物return detectedMarkers.size() > 3 ? detectedMarkers.subList(0, 3) : detectedMarkers;}/*** 显示标识物供用户选择* @param imagePath 原始图像路径* @param candidates 候选标识物列表*/public void showMarkerSelectionDialog(String imagePath, List<Marker> candidates) {Mat image = Imgcodecs.imread(imagePath);if (image.empty()) {throw new RuntimeException("无法读取图像: " + imagePath);}// 在图像上绘制候选标识物边框for (int i = 0; i < candidates.size(); i++) {Rect rect = candidates.get(i).getRect();// 绘制不同颜色的边框(第1名绿色,第2名蓝色,第3名黄色)Scalar color = i == 0 ? new Scalar(0, 255, 0) : i == 1 ? new Scalar(255, 0, 0) : new Scalar(0, 255, 255);Imgproc.rectangle(image, rect.tl(), rect.br(), color, 2);Imgproc.putText(image, "Object" + (i+1), rect.tl(), Imgproc.FONT_HERSHEY_SIMPLEX, 0.8, color, 2);}// 转换为Swing可显示的图像BufferedImage bufferedImage = matToBufferedImage(image);// 创建交互窗口JFrame frame = new JFrame("选择标识物(按1-3键选择,鼠标框选可手动添加)");frame.setSize(image.cols(), image.rows());frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);JLabel label = new JLabel(new ImageIcon(bufferedImage));frame.add(label);// 键盘选择(1-3对应候选标识物)frame.addKeyListener(new java.awt.event.KeyAdapter() {public void keyPressed(java.awt.event.KeyEvent e) {int key = e.getKeyCode() - java.awt.event.KeyEvent.VK_1;if (key >= 0 && key < candidates.size()) {selectedMarker = candidates.get(key);System.out.println("已选择候选" + (key+1) + "作为标识物");saveMarkerTemplate(selectedMarker);frame.dispose();}}});// 鼠标框选(手动选择区域)MouseSelectionHandler mouseHandler = new MouseSelectionHandler(label, image);label.addMouseListener(mouseHandler);label.addMouseMotionListener(mouseHandler);frame.setVisible(true);}/*** 鼠标框选处理器(支持手动选择标识物)*/private class MouseSelectionHandler extends MouseAdapter {private JLabel label;private Mat image;private Point startPoint;private Rect selectionRect;public MouseSelectionHandler(JLabel label, Mat image) {this.label = label;this.image = image;}@Overridepublic void mousePressed(MouseEvent e) {startPoint = e.getPoint();}@Overridepublic void mouseDragged(MouseEvent e) {// 实时绘制框选区域Point endPoint = e.getPoint();selectionRect = new Rect(new org.opencv.core.Point(Math.min(startPoint.x, endPoint.x), Math.min(startPoint.y, endPoint.y)),new org.opencv.core.Point(Math.max(startPoint.x, endPoint.x), Math.max(startPoint.y, endPoint.y)));Mat temp = image.clone();Imgproc.rectangle(temp, selectionRect.tl(), selectionRect.br(), new Scalar(0, 0, 255), 2);label.setIcon(new ImageIcon(matToBufferedImage(temp)));}@Overridepublic void mouseReleased(MouseEvent e) {// 保存手动框选的区域作为标识物if (selectionRect != null && selectionRect.area() > MIN_AREA) {selectedMarker = new Marker(selectionRect, selectionRect.area(), 0, image.submat(selectionRect));System.out.println("已手动选择标识物区域");saveMarkerTemplate(selectedMarker);((JFrame) SwingUtilities.getWindowAncestor(label)).dispose();}}}/*** 保存标识物模板(用于后续匹配)*/private void saveMarkerTemplate(Marker marker) {String templatePath = templateRootPath+"marker_template_" + System.currentTimeMillis() + ".png";Imgcodecs.imwrite(templatePath, marker.getMat());// 同时保存标识物在原图中的坐标(用于计算角度)System.out.println("标识物模板已保存至: " + templatePath);System.out.println("标识物位置: " + marker.getRect());}/*** Mat转BufferedImage(用于Swing显示)*/private BufferedImage matToBufferedImage(Mat mat) {int type = BufferedImage.TYPE_BYTE_GRAY;if (mat.channels() > 1) {type = BufferedImage.TYPE_3BYTE_BGR;}int bufferSize = mat.channels() * mat.cols() * mat.rows();byte[] buffer = new byte[bufferSize];mat.get(0, 0, buffer);BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);final byte[] targetPixels = ((java.awt.image.DataBufferByte) image.getRaster().getDataBuffer()).getData();System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);return image;}/*** 标识物实体类*/public static class Marker {private Rect rect;       // 位置和大小private double area;     // 面积private int vertices;    // 顶点数(形状规则度)private Mat mat;         // 图像数据public Marker(Rect rect, double area, int vertices, Mat mat) {this.rect = rect;this.area = area;this.vertices = vertices;this.mat = mat;}// 优先级计算(面积越大、形状越规则,优先级越高)public double getPriority() {// 顶点数4(矩形)或3(三角形)的标识物加分double shapeScore = (vertices == 4 || vertices == 3) ? 1.5 : 1.0;return area * shapeScore;}// getter方法public Rect getRect() { return rect; }public Mat getMat() { return mat; }}
}

       (2)测试代码Test.java

import java.util.List;/*** 测试自动寻找模版*/
public class Test {public static void main(String[] args) {String stitchedImagePath="d:/test/3-2.jpg";MarkerDetector md=new MarkerDetector();List<MarkerDetector.Marker> ms=md.autoDetectMarkers(stitchedImagePath);md.showMarkerSelectionDialog(stitchedImagePath,ms);}}

(3)测试效果

测试输入的图片3-2.jpg是下图:

运行效果如下图:

我选择保存的是最右边的标识物,保存名称为marker_template_1756440153260,见下图:

3.标识物模版匹配实际图片程序

        (1)模版匹配实际图片MarkerTemplateMatcher.java

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.ArrayList;
import java.util.List;import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;public class MarkerTemplateMatcher {// 加载OpenCV库static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);}// 匹配阈值(0-1,值越大匹配越严格)private static final double MATCH_THRESHOLD = 0.8;// 模板图像private Mat template;// 模板宽度和高度private int templateWidth;private int templateHeight;/*** 加载模板图像* @param templatePath 模板图像路径* @return 是否加载成功*/public boolean loadTemplate(String templatePath) {template = Imgcodecs.imread(templatePath);if (template.empty()) {System.err.println("无法加载模板图像: " + templatePath);return false;}// 转换为灰度图(提高匹配效率)Imgproc.cvtColor(template, template, Imgproc.COLOR_BGR2GRAY);templateWidth = template.cols();templateHeight = template.rows();System.out.println("模板加载成功,尺寸: " + templateWidth + "x" + templateHeight);return true;}/*** 在输入图像中寻找模板匹配位置* @param inputImagePath 输入图像路径* @return 匹配位置的矩形列表*/public List<Rect> findTemplateMatches(String inputImagePath) {List<Rect> matches = new ArrayList<>();// 读取输入图像并转换为灰度图Mat inputImage = Imgcodecs.imread(inputImagePath);if (inputImage.empty()) {System.err.println("无法读取输入图像: " + inputImagePath);return matches;}Mat grayImage = new Mat();Imgproc.cvtColor(inputImage, grayImage, Imgproc.COLOR_BGR2GRAY);// 创建结果矩阵(存储匹配程度)int resultCols = grayImage.cols() - templateWidth + 1;int resultRows = grayImage.rows() - templateHeight + 1;Mat result = new Mat(resultRows, resultCols, CvType.CV_32FC1);// 执行模板匹配Imgproc.matchTemplate(grayImage, template, result, Imgproc.TM_CCOEFF_NORMED);// 寻找匹配值超过阈值的位置Core.MinMaxLocResult mmr = Core.minMaxLoc(result);// 对于多匹配情况,遍历结果矩阵if (Imgproc.TM_CCOEFF_NORMED == Imgproc.TM_CCOEFF_NORMED) {// 单模板最佳匹配if (mmr.maxVal >= MATCH_THRESHOLD) {Point matchLoc = mmr.maxLoc;Rect matchRect = new Rect(new Point(matchLoc.x, matchLoc.y),new Size(templateWidth, templateHeight));matches.add(matchRect);System.out.println("找到匹配位置,置信度: " + mmr.maxVal);} else {System.out.println("未找到符合阈值的匹配,最高置信度: " + mmr.maxVal);}}return matches;}/*** 显示带有匹配框的图像* @param imagePath 原始图像路径* @param matches 匹配位置矩形列表*/public void showMatchingResult(String imagePath, List<Rect> matches) {Mat image = Imgcodecs.imread(imagePath);if (image.empty()) {System.err.println("无法读取图像用于显示: " + imagePath);return;}// 绘制所有匹配位置的矩形框for (int i = 0; i < matches.size(); i++) {Rect rect = matches.get(i);// 绘制红色矩形框(BGR格式)Imgproc.rectangle(image, rect.tl(), rect.br(), new Scalar(0, 0, 255), 2);// 显示匹配序号和置信度putTextWithChinese(image, "匹配" + (i+1), rect.tl());}// 转换为Swing可显示的图像BufferedImage bufferedImage = matToBufferedImage(image);// 创建显示窗口JFrame frame = new JFrame("模板匹配结果");frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);frame.getContentPane().add(new JLabel(new ImageIcon(bufferedImage)));frame.pack();frame.setLocationRelativeTo(null); // 居中显示frame.setVisible(true);}/*** 绘制中文文本(解决OpenCV中文显示问题)*/private void putTextWithChinese(Mat image, String text, Point point) {try {// 转换为BufferedImageBufferedImage bufferedImage = matToBufferedImage(image);Graphics2D g2d = bufferedImage.createGraphics();// 设置字体(使用系统中的中文字体)Font font = new Font("SimHei", Font.PLAIN, 16); // 黑体g2d.setFont(font);g2d.setColor(Color.RED);// 绘制文本g2d.drawString(text, (int)point.x, (int)point.y - 5); // 显示在矩形上方g2d.dispose();// 转换回Matimage.setTo(bufferedImageToMat(bufferedImage));} catch (Exception e) {// 若字体设置失败,使用默认方式绘制(可能显示乱码)Imgproc.putText(image, text, point, Imgproc.FONT_HERSHEY_SIMPLEX, 0.6, new Scalar(0, 0, 255), 2);}}/*** Mat转BufferedImage*/private BufferedImage matToBufferedImage(Mat mat) {int type = BufferedImage.TYPE_BYTE_GRAY;if (mat.channels() > 1) {type = BufferedImage.TYPE_3BYTE_BGR;}int bufferSize = mat.channels() * mat.cols() * mat.rows();byte[] buffer = new byte[bufferSize];mat.get(0, 0, buffer);BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);return image;}/*** BufferedImage转Mat*/private Mat bufferedImageToMat(BufferedImage image) {Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();mat.put(0, 0, data);return mat;}/*** 主方法:演示模板匹配流程*/public static void main(String[] args) {// 创建匹配器实例MarkerTemplateMatcher matcher = new MarkerTemplateMatcher();// 1. 加载模板(替换为你的模板图像路径)String templatePath = "marker_template.jpg"; // 之前保存的标识物模板if (!matcher.loadTemplate(templatePath)) {return;}// 2. 在新图像中寻找匹配(替换为你的测试图像路径)String testImagePath = "new_wine_bottle.jpg"; // 新的酒瓶图像List<Rect> matches = matcher.findTemplateMatches(testImagePath);// 3. 显示匹配结果matcher.showMatchingResult(testImagePath, matches);}
}

        (2)测试程序Test2.java

import java.util.List;import org.opencv.core.Rect;/*** 测试模版加载寻找*/
public class Test2 {public static void main(String[] args) {long a1=System.currentTimeMillis();String stitchedImagePath="d:/test/3-5.jpg";String templateImagePath="d:/test/marker_template_1756440153260.png";MarkerTemplateMatcher mtm = new MarkerTemplateMatcher();System.out.println(System.currentTimeMillis()-a1);mtm.loadTemplate(templateImagePath);		System.out.println(System.currentTimeMillis()-a1);List<Rect> ms=mtm.findTemplateMatches(stitchedImagePath);System.out.println(System.currentTimeMillis()-a1);mtm.showMatchingResult(stitchedImagePath, ms);}}

        (3)测试效果

       测试用的3-5.jpg,我模拟了实际情况,让标识物的内部打了写空心点,并且将标识物水平方向缩短了2个像素(模拟线扫相机丢帧,少了1根线),如下图:

        实际上,人工模拟的干扰,也没有影响预期的效果,程序运行还是找到了目标:

四、总结

 1.还是学习速度,AI大大的帮助了我。我虽然有一点点CV的基础,但是这一次AI写的代码,比我写的好,时间也大大缩短了。但是AI仍然有理解不到位的地方,在我的引导下,快速完成了代码。

2.为什么选择CV而不是AI模型呢?因为AI模型目前做目标检测已经很好了,为什么不选择呢?因为时间,工业场景中,特别是流水线上,对节拍要求很高,基于AI的目标检测达不到这个处理效率。

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

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

相关文章

B树的概述以及插入逻辑

一&#xff0c;B树的概述1.B树(B-树)又称多路平衡查找树&#xff0c;B树所有节点中孩子数量的最大值n称为B树的阶&#xff0c;通常用m表示比如当m为2就是常见的二叉树一颗m阶的B树定义如下&#xff1a;1)每个结点最多有m-1个关键字&#xff1b;2)根节点最少可以只有1个关键字;3…

如何用 Kotlin 在 Android 手机开发一个小闹钟、计时器、秒表

以下是在 Android 上用 Kotlin 开发小闹钟、计时器和秒表的方法&#xff0c;分为核心功能实现和界面设计两部分&#xff1a; 闹钟功能实现 AlarmManager 和 BroadcastReceiver // 设置闹钟 val alarmManager getSystemService(Context.ALARM_SERVICE) as AlarmManager val i…

LeetCode Hot 100 第8天

1. 73 矩阵置零&#xff08;记录标识&#xff09; 链接&#xff1a;题目链接 题解&#xff1a; 题解 时间复杂度O(n*m)&#xff1a; 方案1(空间复杂度O(n m))&#xff1a;matrix[i][j] 0&#xff0c;意味着 第i行、第j列所有元素都要置为0&#xff1b;维护能置为0行、列的集…

Python OpenCV图像处理与深度学习:Python OpenCV开发环境搭建与入门

Python OpenCV入门&#xff1a;环境设置 学习目标 通过本课程&#xff0c;学员们将学习在Windows、macOS和Linux操作系统上安装Python和OpenCV&#xff0c;配置开发环境&#xff0c;以及如何使用Jupyter Notebook和PyCharm等集成开发环境&#xff08;IDE&#xff09;进行基本操…

【论文阅读】SegCLIP:用于高分辨率遥感图像语义分割的多模态视觉语言和快速学习

【论文阅读】SegCLIP&#xff1a;用于高分辨率遥感图像语义分割的多模态视觉语言和快速学习 文章目录【论文阅读】SegCLIP&#xff1a;用于高分辨率遥感图像语义分割的多模态视觉语言和快速学习一、介绍二、联系工作三、方法四、实验结果**数据集**SegCLIP: Multimodal Visual-…

Anaconda、OpenCV安装配置方法

目录 1.Anaconda安装 1.1 国内镜像软件下载 1.2 点击exe&#xff0c;一路下一步安装 1.3 检查安装情况 1.3.1 安装前后系统环境变量变化对比 1.3.2 查看安装路径和版本 1.4 Anaconda自带的python版本查看命令如下&#xff1a; 1.5 修改镜像地址&#xff0c;加快下载包的…

C++函数继承

C函数继承引言C三大特征分别为封装&#xff0c;继承和多态&#xff0c;它们构成了面向对象编程的基石&#xff0c;它们协同工作以提升代码的模块化&#xff0c;可复用性和灵活性封装&#xff1a;提高代码的维护性&#xff08;当程序出现问题时可以准确定位&#xff09;继承&…

瞬态数据表定义Fluent变量

重要说明&#xff1a;本文基于2025R2版本编写&#xff0c;其他版本可能存在差异。1 概述瞬态数据表是定义 Fluent 变量随时间变化规律的profile文件&#xff0c;文件类型为文本文件。瞬态数据表假设所有时刻&#xff0c;被定义的对象都是均匀分布&#xff0c;无法考虑变量在空间…

文本嵌入模型的本质

这是一个非常深刻且重要的问题。我们来详细拆解一下“通用文本嵌入模型”的本质。 我们可以从三个层次来理解它&#xff1a;它是什么&#xff08;What&#xff09;&#xff0c;它如何工作&#xff08;How&#xff09;&#xff0c;以及它为什么重要&#xff08;Why&#xff09;。…

Linux笔记13——shell编程基础-7

补充1.printf %s\t%s 字符串 中&#xff0c;\t一定不要加双引号&#xff0c;这一点和在awk中使用的时候有所不同2.其中%s也可以写成%ns&#xff0c;n可以被用来设置列宽&#xff0c;默认右对齐#打印输出文件系统的使用情况 [rootlocalhost ~]# printf %-30s\t%s\n $(df -h | aw…

【混合开发】Android+WebView视频图片播放硬件加速详解

webview视频播放出现白屏、蓝屏、花屏、黑屏等等 但由于布局结构是androidwebviewH5本地视频等。视频播放导致的异常排查起来十分复杂且没有原生的相关日志 于是需要给webview播放视频进行硬件加速&#xff0c;刚开始以为是一件很简单的配置而已。本着无经验从头开始的原则&am…

Allegro-DDR3实战-差分对-等长设置-区域规则

本章内容&#xff1a; 一&#xff09;Allegro之DDR3设计 (实操干货) 二&#xff09;规则设置具体步骤 DDR3信号表: (eg&#xff1a;镁光MT41J256M16HA-15E) 数据信号 DQ[15:0] DQS[1:0] DM[1:0] DQ:双向数据总线 DQS:数据选通&#xff0c;用于同步数据传…

七牛云OSS空间复制迁移到另外一个空间

创新新的空间时存储地区必须一致 访问控制必须选择公开 1、下载七牛的同步工具并解压 qshell&#xff08;http://developer.qiniu.com/docs/v6/tools/qshell.html&#xff09; 2、解压文件 3、运行cmd登录到七牛账号 qshell account 你的七牛AK 你的七牛SK 你的账号 4、测…

windows中Qwen3‑Coder 与 Claude Code 搭配使用

claude安装命令 npm install -g anthropic-ai/claude-code环境变量配置 set ANTHROPIC_BASE_URLhttps://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy set ANTHROPIC_AUTH_TOKENyour-dashscope-apikey可能还需要配置自己的git环境变量 查看git安装位置 按下Win S打…

thunar 文件管理器实现双击使用 nvim打开

archlinux 中thunar 文件管理器&#xff0c;如何实现双击使用 nvim打开查看。我用的是kitty 终端。 在 Arch Linux Thunar kitty nvim 的环境里&#xff0c;要实现 双击文件 -> 用 nvim 打开&#xff0c;你可以这样配置&#xff1a;设置为默认应用 如果你想 双击直接用 n…

深度学习----卷积神经网络实现数字识别

一、准备工作 导入库&#xff0c;导入数据集&#xff0c;划分训练批次数量&#xff0c;规定训练硬件&#xff08;这部分 import torch from torch import nn # 导入神经网络模块 from torch.utils.data import DataLoader # 数据包管理工具&#xff0c;打包数据 from torch…

鸿蒙Harmony-从零开始构建类似于安卓GreenDao的ORM数据库(四)

目录 一,查询表的所有数据 二,根据条件查询数据 三,数据库升级 前面章节已经讲解了数据库的创建,表的创建,已经增删改等操作。下面我们来讲解一下数据库的查询以及升级操作。 一,查询表的所有数据 先来看看官方文档: query(predicates: RdbPredicates, callback: Asy…

20250829_编写10.1.11.213MySQL8.0异地备份传输脚本+在服务器上创建cron任务+测试成功

0.已知前提条件: 10.1.11.213 堡垒机访问 mysql 8.0 版本 密码在/root/.my.cnf 备份脚本:/data/backup_mysql/mysql_backup.sh alarm_system:动环数据库 exit_and_entry:出入境数据库 logs:备份日志 project_cg_view_prod:采购跟踪系统 all :数据库整体备份 imip_ecb…

PostgreSQL 流复制与逻辑复制性能优化与故障切换实战经验分享

PostgreSQL 流复制与逻辑复制性能优化与故障切换实战经验分享 在高可用和数据安全愈发受到重视的生产环境中&#xff0c;PostgreSQL 复制技术是保障业务连续性的重要手段。本文结合真实生产场景&#xff0c;分享流复制&#xff08;Physical Replication&#xff09;与逻辑复制&…

Django开发规范:构建可维护的AWS资源管理应用

引言 在现代Web开发中,遵循一致的开发规范对于项目的可维护性和团队协作至关重要。本文基于实际的AWS资源管理项目,分享一套经过实践检验的Django开发规范,涵盖模型设计、Admin配置、管理命令和工具类开发等方面。 模型开发规范 数据模型设计原则 良好的数据模型设计是应…