OpenCvSharp 棋盘格标定助手

2023-05-16

  • 使用的是VS调用OpenCvSharp资源库进行一个Winform操作界面编写,网上找了很多开源的程序,发现根本用不了的,用的时候还需要你配置各种电脑系统变量,显得好麻烦。现在弄了个简单的标定助手,可以完美运行,带有棋盘格图像生成工具,操作简单,源码也不复杂。
    这里是
using OpenCvSharp;//需要引用OpenCvSharp
using OpenCvSharp.Extensions;
using Size = OpenCvSharp.Size;

        public Mat ChessBoardMat;
        /// <summary>
        /// 生成棋盘格图像
        /// </summary>
        /// <param name="BoardSize">输入棋盘格角点数量的大小</param>
        /// <param name="ImagePixel">输入棋盘格的像素大小</param>
        /// <returns></returns>
		public Bitmap GenChessBoard(OpenCvSharp.Size BoardSize, OpenCvSharp.Size ImagePixel)
        {
            int perBoardPixel = ImagePixel.Height / BoardSize.Height;
            int basisHeight = (ImagePixel.Height - perBoardPixel * BoardSize.Height) / 2;
            int basisWidth = (ImagePixel.Width - perBoardPixel * BoardSize.Width) / 2;
            if (basisHeight < 0 || basisWidth < 0)
            {
                return null;
            }
            ChessBoardMat = new Mat(ImagePixel, MatType.CV_8UC1, Scalar.All(255));
            int flag;
            for (int j = 0; j < BoardSize.Height; j++)
            {
                for (int i = 0; i < BoardSize.Width; i++)
                {
                    flag = (i + j) % 2;
                    if (flag == 0)
                    {
                        for (int n = j * perBoardPixel; n < (j + 1) * perBoardPixel; n++)
                            for (int m = i * perBoardPixel; m < (i + 1) * perBoardPixel; m++)
                                ChessBoardMat.At<byte>(n + basisHeight, m + basisWidth) = 0;
                    }
                }
            }
            return BitmapConverter.ToBitmap(ChessBoardMat);//返回棋盘格图像结果
            //Cv2.ImWrite("chessBoard1.bmp", image);//这里是保存生成的图像,可以不使用
        }

结果如下:
棋盘格生成工具点击“导入图像”后,选择采集的棋盘格图像所在文件夹,结果如下:
棋盘格标定助手 导入图像

可以在图像列表看到导入结果,在参数设置那里设置正确的棋盘格角点数量后,在图像列表双击图像路径,可以实现棋盘格图像角点的提取显示:
棋盘格标定助手 图像角点显示
可以提取角点之后就可以标定啦!
棋盘格标定助手  标定结果标定完成后,可以进行畸变矫正,这个是进行畸变矫正的结果,在这里并没有写保存矫正结果的代码。
所以只是看看就好

然后所有结果都出来了,并且自动保存结果在图像文件里内!
标定结果数据查看

这里是核心源码,至于Winform的操作代码,这里就不放了。感兴趣的朋友可以去下载看看

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Size = OpenCvSharp.Size;

namespace CvCalibrate
{
    public class Calib_Class
    {
        public Mat ChessBoardMat;
        #region 初始化变量
        /*内外参数*/
        Mat cameraMatrix = new Mat(3, 3, MatType.CV_64FC1, Scalar.All(0)); /* 摄像机内参数矩阵 */
        List<int> point_counts = new List<int>();  // 每幅图像中角点的数量
        Mat distCoeffs = new Mat(1, 12, MatType.CV_64FC1, Scalar.All(0)); /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */  /*加上薄棱镜畸变模型,启用畸变系数S1、S2、S3和S4*/
        List<Mat> TranslationMats = new List<Mat>();  /* 每幅图像的旋转向量 */
        List<Mat> RotationMats = new List<Mat>(); /* 每幅图像的平移向量 */
        /*Mat数据类型转换double的结果*/
        public double[,] CameraParameterArray = new double[3, 3];//摄像机内参数矩阵
        public double[] DistCoeffsArray = new double[12];//摄像机的5个畸变系数:k1,k2,p1,p2,k3 /*加上薄棱镜畸变模型,启用畸变系数S1、S2、S3和S4*/
        public Vec3d[] Rotation; //存放所有图像的3*1旋转向量,每一副图像的旋转向量为一个mat
        public Vec3d[] Translation;//存放所有图像的3*1平移向量,每一副图像的平移向量为一个mat
        public double MeanError = 0.0; /* 所有图像的平均误差的总和 */
        public List<double> TotalError = new List<double>(); /* 每幅图像的平均误差 */
        public Size BoardImageSize = new Size();
        #endregion
        /// <summary>
        /// 角点提取,返回Bitmap数据
        /// </summary>
        /// <param name="imageInput">图像输入</param>
        /// <param name="BoardSize">棋盘格角点数量大小</param>
        /// <returns></returns>
        public Bitmap FindChessboardCorners(Image imageInput, OpenCvSharp.Size BoardSize)
        {
            try
            {
                Point2f[] image_points_buf;  /* 缓存每幅图像上检测到的角点 */
                List<Point2f[]> image_points_seq = new List<Point2f[]>(); /* 保存检测到的所有角点 */
                Mat image = BitmapConverter.ToMat(new Bitmap(imageInput));
                /* 提取角点 */
                Cv2.FindChessboardCorners(image, BoardSize, out image_points_buf);
                Mat view_gray = new Mat();
                Cv2.CvtColor(image, view_gray, ColorConversionCodes.RGB2GRAY);
                /* 亚像素精确化 */
                Point2f[] SubPix_points = Cv2.CornerSubPix(view_gray, image_points_buf, new Size(3, 3), new Size(-1, -1), TermCriteria.Both(30, 0.1));
                image_points_seq.Add(SubPix_points);  //保存亚像素角点
                /* 在图像上显示角点位置 */
                Cv2.DrawChessboardCorners(view_gray, BoardSize, image_points_buf, true); //用于在图片中标记角点
                return BitmapConverter.ToBitmap(view_gray);
            }
            catch (Exception)
            {
                return new Bitmap(imageInput);
            }

        }
        public double Fovx/*沿水平传感器轴的视野*/, Fovy/*沿竖直传感器轴的视野*/, FocalLength/*透镜焦距mm*/, AspectRatio/*fy/fx*/;
        public Point2d Principal/*主点坐标mm*/;
        /// <summary>
        /// 运行标定
        /// </summary>
        /// <param name="ChessBoardFiles">棋盘格图像文件路径</param>
        /// <param name="BoardNum">棋盘格角点数量大小</param>
        /// <param name="ErrorMessage">返回判断的消息</param>
        /// <returns></returns>
        public bool Calibrate(List<string> ChessBoardFiles, Size BoardNum, string ErrorMessage)
        {
            int image_count = 0;  /* 图像数量 */
            Size image_size = new Size();  /* 图像的尺寸 */
            if (ChessBoardFiles.Count() > 0)
            {

                #region 角点提取                 
                Point2f[] image_points_buf;  /* 缓存每幅图像上检测到的角点 */
                List<Point2f[]> image_points_seq = new List<Point2f[]>(); /* 保存检测到的所有角点 */
                /*读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化*/
                for (int i = 0; i < ChessBoardFiles.Count(); i++)
                {
                    try
                    {
                        Mat imageInput = Cv2.ImRead(ChessBoardFiles[i]);
                        image_count++;
                        if (image_count == 1)  //读入第一张图片时获取图像宽高信息
                        {
                            BoardImageSize.Width = image_size.Width = imageInput.Cols;
                            BoardImageSize.Height = image_size.Height = imageInput.Rows;
                        }
                        image_points_buf = FindChessboardCorners(imageInput, BoardNum, ErrorMessage);
                        if (image_points_buf.Count() > 0)
                        {
                            image_points_seq.Add(image_points_buf);
                        }
                        else
                        {
                            ErrorMessage += "图 " + i + ", ";
                        }

                    }
                    catch (Exception Err)
                    {
                        ErrorMessage = " 角点提取失败!" + "\n\r" + Err.Message;
                        return false;
                    }
                }
                #endregion

                #region 标定板初始化
                //棋盘三维信息
                // 初始化标定板上角点的三维坐标
                //生成一个标准的标定板角点坐标集合
                Size square_size = new Size(20, 20);  //初始化标定板上每个棋盘格的大小 
                List<List<Point3f>> object_points = new List<List<Point3f>>(); // 保存标定板上角点的三维坐标
                if (BoardNum.Width > 0)
                {
                    try
                    {
                        for (int t = 0; t < image_count; t++)
                        {
                            List<Point3f> tempPointSet = new List<Point3f>();
                            for (int i = 0; i < BoardNum.Height; i++)
                            {
                                for (int j = 0; j < BoardNum.Width; j++)
                                {
                                    Point3f realPoint;
                                    // 假设标定板放在世界坐标系中z=0的平面上
                                    realPoint.X = i * square_size.Width;
                                    realPoint.Y = j * square_size.Height;
                                    realPoint.Z = 0;
                                    tempPointSet.Add(realPoint);
                                }
                            }
                            object_points.Add(tempPointSet);
                            // 初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板 
                            point_counts.Add(BoardNum.Width * BoardNum.Height);
                        }
                    }
                    catch (Exception Err)
                    {
                        ErrorMessage = "初始化棋盘格失败!" + "\n\r" + Err.Message;
                    }
                }
                else
                {
                    ErrorMessage = "棋盘格大小设置错误!";
                    return false;
                }

                #endregion

                #region 开始标定
                try
                {
                    /*薄棱镜畸变模型,启用畸变系数S1、S2、S3和S4*/
                    /*迭代标准*/
                    TermCriteria criteria = new TermCriteria(CriteriaTypes.Eps | CriteriaTypes.MaxIter, 30, 0.01);
                    Cv2.CalibrateCamera(object_points, image_points_seq, image_size, CameraParameterArray, DistCoeffsArray, out Rotation, out Translation, CalibrationFlags.ThinPrismModel, criteria);

                }
                catch (Exception Err)
                {
                    ErrorMessage = "标定失败!" + "\n\r" + Err.Message;
                    return false;
                }
                #endregion

                #region 数据类型转换
                for (int r = 0; r < CameraParameterArray.GetLength(0); r++)
                {
                    for (int c = 0; c < CameraParameterArray.GetLength(1); c++)
                    {
                        cameraMatrix.At<double>(r, c) = CameraParameterArray[r, c];
                    }
                }

                for (int r = 0; r < DistCoeffsArray.Length; r++)
                {
                    distCoeffs.At<double>(0, r) = DistCoeffsArray[r];
                }
                for (int r = 0; r < Rotation.Length; r++)
                {
                    Mat TempRotation = new Mat(3, 1, MatType.CV_64FC1);

                    TempRotation.At<double>(0, 0) = Rotation[r].Item0;
                    TempRotation.At<double>(1, 0) = Rotation[r].Item1;
                    TempRotation.At<double>(2, 0) = Rotation[r].Item2;
                    RotationMats.Add(TempRotation);

                    Mat TempTrans = new Mat(3, 1, MatType.CV_64FC1);

                    TempTrans.At<double>(0, 0) = Translation[r].Item0;
                    TempTrans.At<double>(1, 0) = Translation[r].Item1;
                    TempTrans.At<double>(2, 0) = Translation[r].Item2;
                    TranslationMats.Add(TempTrans);
                }
                #endregion

                #region 重新投影计算,误差计算
                double total_err = 0.0;            // 所有图像的平均误差的总和 
                double Error;                      //每幅图像的平均误差 

                for (int i = 0; i < image_count; i++)
                {
                    try
                    {
                        List<Point3f> tempPointSet = object_points[i];
                        /* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
                        Mat NewProjectPoints = new Mat();/* 保存重新计算得到的投影点 */
                        Mat jacobian = new Mat();//雅可比矩阵
                        Cv2.ProjectPoints(InputArray.Create<Point3f>(tempPointSet), RotationMats[i], TranslationMats[i], cameraMatrix, distCoeffs, NewProjectPoints, jacobian, 0);
                        List<Point2f> NewProjectPointsToPoint2f = new List<Point2f>(); /* 保存重新计算得到的投影点,格式转换 */
                        {
                            string[] PointsArray = Cv2.Format(NewProjectPoints, FormatType.CSV).Split('\n');//分割出来最后一个回车符号占了一个空间
                            for (int r = 0; r < PointsArray.Length - 1; r++)
                            {
                                Point2f Temp = new Point2f();//临时缓存
                                string[] PointTemp = PointsArray[r].Split(',');
                                Temp.X = float.Parse(PointTemp[0]);
                                Temp.Y = float.Parse(PointTemp[1]);
                                NewProjectPointsToPoint2f.Add(Temp);
                            }
                        }

                        /* 计算新的投影点和旧的投影点之间的误差*/
                        Point2f[] OldProjectPoints = image_points_seq[i];
                        Mat tempImagePointMat = new Mat(1, OldProjectPoints.Length, MatType.CV_32FC2);
                        Mat image_points2Mat = new Mat(1, NewProjectPoints.Rows, MatType.CV_32FC2);
                        for (int j = 0; j < OldProjectPoints.Count(); j++)
                        {
                            image_points2Mat.At<Vec2f>(0, j) = new Vec2f(NewProjectPointsToPoint2f[j].X, NewProjectPointsToPoint2f[j].Y);
                            tempImagePointMat.At<Vec2f>(0, j) = new Vec2f(OldProjectPoints[j].X, OldProjectPoints[j].Y);
                        }
                        Error = Cv2.Norm(image_points2Mat, tempImagePointMat, NormTypes.L2);//当前图像的投影误差
                        total_err += Error * Error;
                        TotalError.Add(Error);
                        MeanError += Error /= point_counts[i];//总的平均误差
                        double 重投影误差3 = (total_err / image_count);
                    }
                    catch (Exception Err)
                    {
                        ErrorMessage = "误差计算失败!" + "\n\r" + Err.Message;
                        return false;
                    }
                }
                #endregion

                #region 旋转矩阵计算
                List<Mat> AllRotation_Matrix = new List<Mat>(); /* 保存每幅图像的旋转矩阵 */
                for (int i = 0; i < image_count; i++)
                {
                    try
                    {
                        Mat rotation_matrix = new Mat(3, 3, MatType.CV_64FC1, Scalar.All(0));
                        /* 将旋转向量转换为相对应的旋转矩阵 */
                        /*Rodrigues()可以将旋转向量转化为旋转矩阵,也可以将旋转矩阵转化为旋转向量。旋转向量指定了旋转轴,同时它的模长也指定了旋转角度。*/
                        Cv2.Rodrigues(TranslationMats[i], rotation_matrix);
                        AllRotation_Matrix.Add(rotation_matrix);
                    }
                    catch (Exception Err)
                    {
                        ErrorMessage = "旋转矩阵计算失败!" + "\n\r" + Err.Message;
                        return false;
                    }

                }
                #endregion
                //Mat Rvec = new Mat();
                //Mat Tvec = new Mat();
                //Cv2.SolvePnP(InputArray.Create<Point3f>(object_points[0]), InputArray.Create<Point2f>(image_points_seq[0]), cameraMatrix, distCoeffs, Rvec, Tvec);
                //double[] R = MatToDouble(Rvec);
                //double[] T = MatToDouble(Tvec);
                Cv2.CalibrationMatrixValues(cameraMatrix, BoardImageSize, 5.3, 7.2, out Fovx, out Fovy, out FocalLength, out Principal, out AspectRatio);

            }
            else
            {
                ErrorMessage = "输入图像路径为空!";
                return false;
            }
            return true;
        }

        private delegate Point2f[] FindCornersDelegate(Mat Src, Size BoardNum, string ErrorMessage);

        /// <summary>
        /// 角点提取
        /// </summary>
        /// <param name="Src">图源</param>
        /// <param name="BoardNum">棋盘格角点数量大小</param>
        /// <param name="ErrorMessage">返回判断的消息</param>
        /// <returns></returns>
        private static Point2f[] FindChessboardCorners(Mat Src, Size BoardNum, string ErrorMessage)
        {
            Point2f[] image_points_buf = new Point2f[BoardNum.Height * BoardNum.Width];  /* 缓存每幅图像上检测到的角点 */
            Point2f[] SubPix_points = new Point2f[BoardNum.Height * BoardNum.Width];
            try
            {
                /* 提取角点 */
                if (!Cv2.FindChessboardCorners(Src, BoardNum, out image_points_buf))
                {
                    //粗提取角点,若无法提取则返回失败,反之进行精细化提取
                    ErrorMessage = " 角点提取失败!";
                }
                else
                {
                    Mat view_gray = new Mat();
                    Cv2.CvtColor(Src, view_gray, ColorConversionCodes.RGB2GRAY);
                    SubPix_points = Cv2.CornerSubPix(view_gray, image_points_buf, new Size(3, 3), new Size(-1, -1), TermCriteria.Both(30, 0.1));//对粗提取的角点进行精确化
                    //Cv2.Find4QuadCornerSubpix(view_gray, image_points_buf, new Size(5, 5)); //对粗提取的角点进行精确化
                }
            }
            catch (Exception Err)
            {
                ErrorMessage = Err.Message;
            }
            return SubPix_points;
        }

        #region 类型转换
        static double[] MatToDouble(Mat InMat)
        {
            if (InMat.Rows >= 1 && InMat.Cols == 1)
            {
                double[] OutDouble = new double[InMat.Rows];
                for (int i = 0; i < InMat.Rows; i++)
                {
                    OutDouble[i] = InMat.At<double>(i);
                }
                return OutDouble;
            }
            else if (InMat.Rows == 1 && InMat.Cols >= 1)
            {
                double[] OutDouble = new double[InMat.Cols];
                for (int i = 0; i < InMat.Cols; i++)
                {
                    OutDouble[i] = InMat.At<double>(i);
                }
                return OutDouble;
            }
            else
            {
                return null;
            }
        }
        static double[,] MatToDouble2D(Mat InMat)
        {
            if (InMat.Rows >= 1 && InMat.Cols >= 1)
            {
                double[,] OutDouble = new double[InMat.Rows, InMat.Cols];
                for (int i = 0; i < InMat.Rows; i++)
                {
                    for (int j = 0; j < InMat.Cols; j++)
                    {
                        OutDouble[i, j] = InMat.At<double>(i, j);
                    }
                }
                return OutDouble;
            }
            else
            {
                return null;
            }
        }
        static Mat DoubleToMat(double[] InDouble)
        {
            Mat OutMat = new Mat(1, InDouble.Length, MatType.CV_64FC1);
            for (int r = 0; r < InDouble.Length; r++)
            {
                OutMat.At<double>(0, r) = InDouble[r];
            }
            return OutMat;
        }
        static Mat Double2DToMat(double[,] InDouble)
        {
            Mat OutMat = new Mat(InDouble.GetLength(0), InDouble.GetLength(1), MatType.CV_64FC1);
            for (int r = 0; r < InDouble.GetLength(0); r++)
            {
                for (int c = 0; c < InDouble.GetLength(1); c++)
                {
                    OutMat.At<double>(r, c) = InDouble[r, c];
                }

            }
            return OutMat;
        }
        #endregion



       
    }
}

付费资源,各取所需吧,花了时间和心思做出来的东西让我免费共享是不可能的。
项目资源下载
对了,下载的源码里面有畸变矫正功能的,但是参数那些暂时没设置正确,所以矫正出来的图像似乎没那么准确,有兴趣的朋友可以去研究下,其实所有的代码都是可以参考OpenCv的,只不过是放在了C#下,有些变量类型略有不同,具体怎么样看看它的类就知道了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCvSharp 棋盘格标定助手 的相关文章

  • QT资源文件(.qrc)的编写与应用

    qrc文件 xff0c 这个是Qt的资源文件 xff0c 如果在pro文件中不包含的话 xff0c 在编译的时候会提示找不到相应资源的错误 xff1b 下面说一下手动修改pro和编写qrc文件的方法 我们直接在命令行下执行qmake pro
  • linux 查看硬盘内存使用情况

    sudo rm rf home wukai local share Trash 清空回收站
  • 耗时统计、日志

    linux struct timeval t1 t2 double timeuse gettimeofday amp t1 NULL foo gettimeofday amp t2 NULL timeuse 61 t2 tv sec t1
  • Ubuntu磁盘分区

    磁盘格式化 xff1a 低级格式化 xff1a 空白磁盘划分柱面 分区以及磁道 高级格式化 xff1a 低级格式化后的逻辑上的结构化 即建立文件系统 磁盘设备命名 xff1a IDE设备由内部设备连接来区分 xff0c 最多连接4个设备 x
  • 流量变现的10种方式

    在互联网飞速发展的今天 xff0c 流量就等于金钱 xff0c 流量越大意味着赚的钱越多 流量如何变现呢 xff1f 以下10种方式可供参考 xff1a 打造个人品牌变现 xff1a 通过写文章或发布短视频 xff0c 提高自己的知名度 x
  • ubuntu 下 .7z 文件解压时,子文件夹内的内容被解压到根文件夹问题

    7z e log4cplus 2 0 8 7z o home wukai Documents log4cplus 参数使用 e 时 xff0c 会导致子文件夹内的内容被解压到根文件夹 xff0c 导致子文件夹没东西 xff0c 且覆盖了根文
  • configure: error: cannot find sources (src/logger.cxx) in . or ..

    配置的时候 xff0c 找不到文件 查看下src文件夹下是不是没有这个文件 xff0c 如果没有 xff0c 可能性有一下两个 1 解压的时候出错 xff0c 导致此文件被解压到其他文件夹 xff1b xff08 参考https mp cs
  • windows下python下载及安装

    下载python安装包 进入python官网 xff1a https www python org 鼠标移动到 Downloads gt 34 Windows 34 上 xff0c 可以看到最新版本是3 11 3版本 点击 Windows
  • 修改环境变量

    点击 windows 按钮 xff0c 输入 环境 xff0c 点击右侧的 编辑系统环境变量 点击 环境变量 按钮 按如下顺序将python添加到环境变量中 然后再把所有弹框的确定按钮都点下
  • windows下创建python文件

    1 打开python IDLE 按下 windows 按钮 xff0c 输入python xff0c 单击 IDLE Python 3 9 64 bit 点击File gt New File 新文件未命令 xff0c 内容空 随意编辑代码
  • python代码注释

    在python中 xff0c 存在三种类型的注释 xff1a 单行注释 多行注释和中文声明注释 1 单行注释 xff08 在需要注释的内容前面加 xff09 注释内容 2 多行注释 xff08 将要注释的内容包含在 或者 内 xff09 3
  • python3.9.13 IDLE设置缩进值

    Options gt 34 Configure IDLE 34 gt 34 Windows 34 Indent spaces 即是缩进值
  • unindent does not match any outer indentation level

    python运行时 xff0c 报错 unindent does not match any outer indentation level 有某行的缩进和其他行不匹配
  • python分行

    方式一 xff1a print 34 123 34 34 456 34 方式二 xff1a print 34 wer asd 34 输出 123456 werasd

随机推荐

  • python命名规范

    1 模块名 xff1a 尽量短小 xff0c 全部小写 xff0c 可以使用下划线分隔多个字母 如 xff1a func 1 func 2 2 类名 xff1a 采用单词首字母大写的方式 如 xff1a Student Teacher 3
  • YOLOv5之autoanchor看这一篇就够了

    简单粗暴 xff0c 废话也不罗嗦了 xff0c 学习目的就是解决下面三个问题 xff0c 1 默认anchor t设置为4 xff0c 这个参数如何调整 xff1f 有没有必要调整 xff1f xff08 首先网上很多说这个参数是长宽比是
  • 反转一个长字符串中的子字符串

    第一次练习写博客 xff0c 记录下自己感觉满意的成果吧 include lt stdio h gt include lt string h gt bool findPosition char sur char dst int amp st
  • c中全局变量,全局结构体使用

    1 在A 中定义的函数 xff0c 如何在 B 中调用 xff1f 如果有头文件 xff0c 在头文件中声明 xff0c 在B 文件中 include 头文件就可以了 如果是在 c 文件中声明的 xff0c 在 B 中加 extent 声明
  • Vue3展示Markdown内容

    起因 想要搭建一个个人网站 xff0c 然后在网站上展示个人信息以及平时学习或者使用框架的一些内容 所以需要一个能够将markdown内容转化到页面上展示 xff08 就类似于github或者各大博客网站 xff09 个人网站是vue3 x
  • debian linux 添加永久环境变量

    写在前面的话 搜索linux添加环境变量 xff0c 网上已经有很多的教程 xff0c 本来就几个命令还是把我搞的好惨 xff0c 几个坑大牛们不指出来 xff0c 我这小白就卡在里面了 xff0c 写下血泪史供参考 关于环境变量 expo
  • CLion、IDEA、Pycharm等用WSL访问不了环境变量的解决方案——更新于2021.12

    目录 相关文献PowerShell解决方案 博主全网搜索过很多教程 xff0c 各种碰壁不成功 xff0c 最终使用了PowerShell成功的 本文将介绍PowerShell的成功方法和几个替代方案 博主使用WSL是Ubuntu 20 0
  • Linux下安装xrdp实现远程桌面

    使用rdp协议访问远程Linux桌面 一般情况下 xff0c 如果需要登陆远程Linux系统 xff0c 我们会使用ssh telnet来完成 xff0c 如果需要登陆到远程Linux系统的桌面环境 xff0c 我们可能会使用VNC VNC
  • 树莓派——xrdp win10远程登录以及蓝屏问题

    1 安装xrdp 使用Putty命令行输入以下命令 sudo apt get install xrdp sudo apt get install tightvncserver xrdp 安装完成后 xff0c 重启xrdp服务器 sudo
  • 使用lnmp安装Nextcloud出现404问题解决方法

    最新消息 特大消息特大消息 xff0c 由于答主解决不了后续出现的WEBDAV接口错误问题 xff0c 因此更改了安装方式 61 61 61 61 61 DOCKER xff01 装完之后感慨一下 xff0c docker大法真好 参考教程
  • 笔记:1. Centos 安装 mpicc

    心情 xff1a 历时一年 xff0c 考上了研究生 xff0c 从此踏上第一性原理计算的道路 是有点小开心 xff0c 因为以后可以做自己喜欢的事情 xff0c 剩下的就是怎么通过做自己喜欢的事挣点钱 xff0c 养活自己 正文 目的 x
  • 【Java】对两个Set取交集,差集,并集

    1 取交集 xff08 取两个集合中都存在的元素 xff09 HashSet lt String gt setA 61 new HashSet lt gt HashSet lt String gt setB 61 new HashSet l
  • nvidia-smi报错:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver 原因及避坑解决方案

    由于断电 xff0c 服务器重启了 xff0c 当再次跑实验时 xff0c 发现cuda不可用 xff0c 于是输入 nvidia smi 才发现了一个错误 xff0c 如下 xff1a NVIDIA SMI has failed beca
  • 【Linux】Debian的下载、安装、图形化界面,多图杀猫

    Linux的版本众多 xff0c 同时相对于非专业用户少见 不像Windows系统那样大众 xff0c 稍微有些知识都知道 xff0c 配置低一点的机器就选择Windows XP Professional SP3 xff0c 搞Asp的用W
  • 【iOS】表视图

    iOS的表视图并不简单 xff0c 它是需要修改 h中加两个委托进去 xff0c 同时在 m文件实现一系列固定的函数 xff0c 才能完成表视图的创建 一切犹如当初点击空白处关闭键盘需要一段代码才能实现一样 xff0c 表视图的创建也不像安
  • win10+anconda+tensorflow安装

    最近由于需要用到深度学习 xff0c 经过一番调研发现tensorflow依旧是工业界模型实现的主流框架 xff0c 于是自己尝试安装tensorflow 原以为直接采用pip就可以直接搞定 xff0c 只能怪自己太天真 xff0c 刚开始
  • Ubuntu 19.04编译Android源码缺少libtinfo.so.5问题

    Ubuntu 19 04 Manjro编译Android Pie源码缺少libtinfo so 5问题 背景 使用ubuntu19 04编译Android源码的时候 xff0c 报缺少libtinfo so 5 解决方法 通过find命令查
  • shell编程的控制结构及其if语句

    控制结构 shell具有般高级程序设计语言所具有的控制结构和其他复杂功能 xff0c 如if语句 case语句 循环结构 函数等 其实在shell 中 xff0c 这些控制结构也被称为命令为了符合程序设计的习惯 xff0c 才把它们称为语句
  • 快速给图片加水印的方法

    快速给图片加水印的方法 xff01 图片添加水印后可以杜绝图不被别人随意使用 xff0c 能保护自己的知识产权不被侵犯 xff0c 所以我们在工作中经常先给图片添加水印 xff0c 然后再将图片对外发布 xff0c 这是一个比较常见的事情
  • OpenCvSharp 棋盘格标定助手

    使用的是VS调用OpenCvSharp资源库进行一个Winform操作界面编写 xff0c 网上找了很多开源的程序 xff0c 发现根本用不了的 xff0c 用的时候还需要你配置各种电脑系统变量 xff0c 显得好麻烦 现在弄了个简单的标定