鲁鹏老师三维重建课程之单视图重建

article/2025/8/8 12:25:23

配置Json环境

       使用Jsoncpp包中的.cpp和 .h文件
       解压上面下载的 Jsoncpp 文件,把 jsoncpp-src-0.5.0文件拷贝到工程目录下, 将 jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json 和 jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\src\lib_json 目录里的文件包含到VS工程中,在VS工程的属性C/C++下General中 Additional Include Directories 包含头文件目录 .\jsoncpp-src-0.5.0\include 。在使用的cpp文件中 包含json头文件即可,如: #include "json/json.h" 。将 json_reader.cpp、 json_value.cpp和 json_writer.cpp三个文件的Precompiled Header属性设置为 Not Using Precompiled Headers, 否则编译会出现错误。

试了很多方法,上述方法亲测可用。

准备工作

读图解析Json文件及声明变量

    Mat src = imread(".//images//chessboard.jpg");//声明一些存储直线点的变量int i=0;vector < vector<Point2d> > Points;vector<Point2d> XZ_line, YZ_line, XY_line, XZ_line1, YZ_line1, XY_line1;Points.push_back(XZ_line);Points.push_back(YZ_line);Points.push_back(XY_line);Points.push_back(XZ_line1);Points.push_back(YZ_line1);Points.push_back(XY_line1);Point2d orignPoint;//第一步先解析Json数据//用来判断是线还是交点的点string shape_type = "line";//用来区分线条的类型vector<string> linetype;string c = ",";linetype.push_back("XZ_line");linetype.push_back("YZ_line");linetype.push_back("XY_line");linetype.push_back("XZ_line'");linetype.push_back("YZ_line'");linetype.push_back("XY_line'");//声明读取Json文件变量Json::Reader reader;Json::Value root;ifstream in(".//labelme_data//chessboard_line.json", ios::binary);if (!in.is_open()){cout << "打开文件错误\n";return 0;}if (reader.parse(in,root)){int temp = root["shapes"].size();for (int m =0; m < temp; m++){string shapetype = root["shapes"][m]["shape_type"].asString();//判断是否为直线点,还是交点if (shapetype == shape_type){string templinetype = root["shapes"][m]["label"].asString();for (; i < linetype.size(); i++){if (templinetype == linetype[i]){//得到points标签下的数据(此时为string类型)int temppointsize = root["shapes"][m]["points"].size();for (int j = 0; j < temppointsize; j++){string strpoint = root["shapes"][m]["points"][j].toStyledString();//对读取到的字符串进行处理,删除[]和空格字符strpoint.erase(strpoint.find(' '),1);strpoint.erase(strpoint.find('['), 1);strpoint.erase(strpoint.find(' '), 1);strpoint.erase(strpoint.find(']'), 1);//将该字符串按逗号分割vector<string> res;SplitString(strpoint, res, c);//将字符串转为doublePoint2d temppoint;temppoint.x = atof(res[0].c_str());temppoint.y = atof(res[1].c_str());Points[i].push_back(temppoint);}}}i = 0;}//原点位置else if (shapetype == "point"){//得到points标签下的数据(此时为string类型)string strpoint = root["shapes"][m]["points"].toStyledString();//对读取到的字符串进行处理,删除[]和空格字符strpoint.erase(strpoint.find(' '), 1);strpoint.erase(strpoint.find('['), 1);strpoint.erase(strpoint.find('['), 1);strpoint.erase(strpoint.find(' '), 1);strpoint.erase(strpoint.find(']'), 1);strpoint.erase(strpoint.find(']'), 1);//将该字符串按逗号分割vector<string> res;SplitString(strpoint, res, c);//将字符串转为doubleorignPoint.x = atof(res[0].c_str());orignPoint.y = atof(res[1].c_str());}}in.close();}

读取到的图像如下:

 将Json文件里面标记的直线和点加载到图片上,并绘制出来可视化

    //点读取完毕,根据点将线条画在图上//复制一张图像//YZ_line, XY_line, XZ_line1, YZ_line1, XY_line1;Mat src1 = src.clone();for (int k = 0; k < Points.size(); k++){int tempSize = Points[k].size()/2;for (int n = 0; n < tempSize; n++){switch (k){case 0:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(0, 0, 255), 1);XZ_line.push_back(Points[k][2 * n]);XZ_line.push_back(Points[k][2 * n+1]);break;case 1:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(0, 255, 0), 1);YZ_line.push_back(Points[k][2 * n]);YZ_line.push_back(Points[k][2 * n + 1]);break;case 2:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(255, 0, 0), 1);XY_line.push_back(Points[k][2 * n]);XY_line.push_back(Points[k][2 * n + 1]);break;case 3:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(0, 255, 255), 1);XZ_line1.push_back(Points[k][2 * n]);XZ_line1.push_back(Points[k][2 * n + 1]);break;case 4:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(255, 255, 0), 1);YZ_line1.push_back(Points[k][2 * n]);YZ_line1.push_back(Points[k][2 * n + 1]);break;case 5:line(src1, Points[k][2 * n], Points[k][2 * n + 1], Scalar(255, 0, 255), 1);XY_line1.push_back(Points[k][2 * n]);XY_line1.push_back(Points[k][2 * n + 1]);break;default:break;}}}

加载完,不同平面的直线用不同颜色绘制的直线和点如下图所示:

 计算影消点

计算影消点,就是根据上面各个平面平行的直线,拟合出平行直线的交点。平行的直线本该没有交点,但经过摄影几何的透视变换,现实世界坐标系下的平行线都会相交于一点,这个点就是影消点,也就是世界坐标系里面的无穷远点,两条平行直线相交于无穷远处。但在摄影几何下,经过透视变换,无穷远点变为影消点,影消点在图像坐标系下可以求。

无穷远点变为影消点最直观的例子,拍摄一条火车铁轨,铁轨最终在图像里面一个点相交。

    //接下来求图像上的影消点//即计算两个平面平行线的交点//先计算XZ平面,两条平行线的交点//计算出来的line为Vec4f类型,即line[0-3]//斜率为line[1]/line[0],并过点(line[2],line[3])//先将其转为向量相乘的形式即l·x=0的形式,这里l其实为l的转置//l为(line[1],-line[0],-line[1]*line[2]+line[0]*line[3])vector<Vec3d> vecLineXZ;vector<Vec3d> vecLineYZ;vector<Vec3d> vecLineXY;vector<Vec3d> vecLineXZ1;vector<Vec3d> vecLineYZ1;vector<Vec3d> vecLineXY1;for (int i = 0; i < vecXZLine.size(); i++){Vec3d tempvec;tempvec[0] = vecXZLine[i][1];tempvec[1] = -vecXZLine[i][0];tempvec[2] = -vecXZLine[i][1] * vecXZLine[i][2] + vecXZLine[i][0] * vecXZLine[i][3];vecLineXZ.push_back(tempvec);}for (int i = 0; i < vecYZLine.size(); i++){Vec3d tempvec;tempvec[0] = vecYZLine[i][1];tempvec[1] = -vecYZLine[i][0];tempvec[2] = -vecYZLine[i][1] * vecYZLine[i][2] + vecYZLine[i][0] * vecYZLine[i][3];vecLineYZ.push_back(tempvec);}for (int i = 0; i < vecXYLine.size(); i++){Vec3d tempvec;tempvec[0] = vecXYLine[i][1];tempvec[1] = -vecXYLine[i][0];tempvec[2] = -vecXYLine[i][1] * vecXYLine[i][2] + vecXYLine[i][0] * vecXYLine[i][3];vecLineXY.push_back(tempvec);}for (int i = 0; i < vecXZ1Line.size(); i++){Vec3d tempvec;tempvec[0] = vecXZ1Line[i][1];tempvec[1] = -vecXZ1Line[i][0];tempvec[2] = -vecXZ1Line[i][1] * vecXZ1Line[i][2] + vecXZ1Line[i][0] * vecXZ1Line[i][3];vecLineXZ1.push_back(tempvec);}for (int i = 0; i < vecYZ1Line.size(); i++){Vec3d tempvec;tempvec[0] = vecYZ1Line[i][1];tempvec[1] = -vecYZ1Line[i][0];tempvec[2] = -vecYZ1Line[i][1] * vecYZ1Line[i][2] + vecYZ1Line[i][0] * vecYZ1Line[i][3];vecLineYZ1.push_back(tempvec);}for (int i = 0; i < vecXY1Line.size(); i++){Vec3d tempvec;tempvec[0] = vecXY1Line[i][1];tempvec[1] = -vecXY1Line[i][0];tempvec[2] = -vecXY1Line[i][1] * vecXY1Line[i][2] + vecXY1Line[i][0] * vecXY1Line[i][3];vecLineXY1.push_back(tempvec);}//求XZ平面的影消点Vec3d testVanishPoint = RobertColins(XZ_line, src.cols, src.rows);Vec3d pointvanishXZvec = vecLineXZ[0].cross(vecLineXZ[vecLineXZ.size() - 1]);//将齐次点形式转为欧式坐标Point2d pointvanishXZ = Point2d(pointvanishXZvec[0] / pointvanishXZvec[2], pointvanishXZvec[1] / pointvanishXZvec[2]);//将图片放大,将影消点可视化Mat dst(6060, 6060, CV_8UC3, Scalar(255, 255, 255));Rect roiRect = Rect(2827, 2827, src.cols, src.rows);src1.copyTo(dst(roiRect));//定义偏移量Point2d dispoint = Point2d(2828, 2828);line(dst, XZ_line[0] + dispoint, pointvanishXZ + dispoint, Scalar(0, 0, 255), 1);line(dst, XZ_line[XZ_line.size() - 1] + dispoint, pointvanishXZ + dispoint, Scalar(0, 0, 255), 1);//求YZ平面的影消点Vec3d pointvanishYZvec = vecLineYZ[0].cross(vecLineYZ[vecLineYZ.size() - 1]);Point2d pointvanishYZ = Point2d(pointvanishYZvec[0] / pointvanishYZvec[2], pointvanishYZvec[1] / pointvanishYZvec[2]);line(dst, YZ_line[1] + dispoint, pointvanishYZ + dispoint, Scalar(0, 255, 0), 1);line(dst, YZ_line[YZ_line.size() - 1] + dispoint, pointvanishYZ + dispoint, Scalar(0, 255, 0), 1);//求XY平面的影消点Vec3d pointvanishXYvec = vecLineXY[0].cross(vecLineXY[vecLineXY.size() - 1]);Point2d pointvanishXY = Point2d(pointvanishXYvec[0] / pointvanishXYvec[2], pointvanishXYvec[1] / pointvanishXYvec[2]);line(dst, XY_line[1] + dispoint, pointvanishXY + dispoint, Scalar(255, 0, 0), 1);line(dst, XY_line[XY_line.size() - 1] + dispoint, pointvanishXY + dispoint, Scalar(255, 0, 0), 1);//求XZ'平面的影消点Vec3d pointvanishXZ1vec = vecLineXZ1[0].cross(vecLineXZ1[vecLineXZ1.size() - 1]);Point2d pointvanishXZ1 = Point2d(pointvanishXZ1vec[0] / pointvanishXZ1vec[2], pointvanishXZ1vec[1] / pointvanishXZ1vec[2]);line(dst, XZ_line1[0] + dispoint, pointvanishXZ1 + dispoint, Scalar(0, 255, 255), 1);line(dst, XZ_line1[XZ_line1.size() - 1] + dispoint, pointvanishXZ1 + dispoint, Scalar(0, 255, 255), 1);//求YZ'平面的影消点Vec3d pointvanishYZ1vec = vecLineYZ1[0].cross(vecLineYZ1[vecLineYZ1.size() - 1]);Point2d pointvanishYZ1 = Point2d(pointvanishYZ1vec[0] / pointvanishYZ1vec[2], pointvanishYZ1vec[1] / pointvanishYZ1vec[2]);line(dst, YZ_line1[1] + dispoint, pointvanishYZ1 + dispoint, Scalar(255, 255, 0), 1);line(dst, YZ_line1[YZ_line1.size() - 1] + dispoint, pointvanishYZ1 + dispoint, Scalar(255, 255, 0), 1);//求XY'平面的影消点Vec3d pointvanishXY1vec = vecLineXY1[0].cross(vecLineXY1[vecLineXY1.size() - 1]);Point2d pointvanishXY1 = Point2d(pointvanishXY1vec[0] / pointvanishXY1vec[2], pointvanishXY1vec[1] / pointvanishXY1vec[2]);line(dst, XY_line1[1] + dispoint, pointvanishXY1 + dispoint, Scalar(255, 0, 255), 1);line(dst, XY_line1[XY_line1.size() - 1] + dispoint, pointvanishXY1 + dispoint, Scalar(255, 0, 255), 1);//至此,各个平面的影消点都已求出来//根据XZ、YZ、XY平面的影消点,进行相机内参标定,求解W矩阵vector<Point2d> vanishPointVec;vanishPointVec.push_back(pointvanishXZ);vanishPointVec.push_back(pointvanishYZ);vanishPointVec.push_back(pointvanishXY);return 0;
}

求得影消点的图片如下图所示:

 计算影消点时,用到了柯林斯算法,该算法如下:

//罗伯特·柯林斯方法求影消点
//输入参数为直线的端点,图像的宽高
//输出为影消点的齐次坐标形式
Vec3d RobertColins(vector<Point2d> vecLinePoints,int cols,int rows)
{Vec3d vanishPoint;int size = vecLinePoints.size();//防止坐标点差异过大造成求解精度下降,进行偏移int offset = (cols + rows) / 4;//这里直线端点,以两个点为一组代表一条直线//因此size必为偶数//得出各条直线的方向向量vector <Vec3d> Lines;for (int i = 0; i < size/2; i++){Vec3d startPoint, endPoint;startPoint[0] = (vecLinePoints[2 * i].x-offset);startPoint[1] = (vecLinePoints[2 * i].y-offset);startPoint[2] = offset;endPoint[0] = (vecLinePoints[2 * i + 1].x - offset);endPoint[1] = (vecLinePoints[2 * i + 1].y - offset);endPoint[2] = offset;//两个点坐标向量的叉乘等于,过该两点的直线齐次坐标向量Lines.push_back(startPoint.cross(endPoint));}/*声明一个Mat M形成3×3的“二阶矩”矩阵M为[a_i*a_i        a_i*b_i        a_i*c_i]M = sum [a_i*b_i        b_i*b_i        c_i*b_i][a_i*c_i        b_i*c_i        c_i*c_i]其中取i = 1到n的和。注意,M是对称矩阵。*/Mat M = (Mat_<double>(3, 3)<<0,0,0,0,0,0,0,0,0);for (int i = 0; i < size / 2; i++){Mat tempM = (Mat_<double>(3, 3));tempM.at<double>(0, 0) = Lines[i][0] * Lines[i][0];tempM.at<double>(0, 1) = Lines[i][0] * Lines[i][1];tempM.at<double>(0, 2) = Lines[i][0] * Lines[i][2];tempM.at<double>(1, 0) = Lines[i][1] * Lines[i][0];tempM.at<double>(1, 1) = Lines[i][1] * Lines[i][1];tempM.at<double>(1, 2) = Lines[i][1] * Lines[i][2];tempM.at<double>(2, 0) = Lines[i][2] * Lines[i][0];tempM.at<double>(2, 1) = Lines[i][2] * Lines[i][1];tempM.at<double>(2, 2) = Lines[i][2] * Lines[i][2];M = M + tempM;}//对M矩阵进行特征值分解Mat eigenvector = (Mat_<double>(3, 3));Mat eigenvalue = (Mat_<double>(3, 1));eigen(M, eigenvalue, eigenvector);vanishPoint[0] = eigenvector.at<double>(0, 2)*(offset / (eigenvector.at<double>(0, 2))) + offset;vanishPoint[1] = eigenvector.at<double>(1, 2)*(offset / (eigenvector.at<double>(0, 2))) + offset;vanishPoint[2] = 1;return vanishPoint;
}

解析Json文件用到的字符串处理方法:

//分割points字符串类型的点
void SplitString(const string& s, vector<string>& v, const string& c)
{string::size_type pos1, pos2;pos2 = s.find(c);pos1 = 0;while (string::npos != pos2){v.push_back(s.substr(pos1, pos2 - pos1));pos1 = pos2 + c.size();pos2 = s.find(c, pos1);}if (pos1 != s.length())v.push_back(s.substr(pos1));
}

http://chatgpt.dhexx.cn/article/d6GI3sLO.shtml

相关文章

常用 Linux 软件汇总!很全,但不敢说最全

点击下方公众号「关注」和「星标」 回复“1024”获取独家整理的学习资料&#xff01; 音频 Airtime - Airtime 是一款用于调度和远程站点管理的开放广播软件 Ardour - 在 Linux 上录音&#xff0c;编辑&#xff0c;和混音 Audacious - 开源音频播放器&#xff0c;按你想要的方式…

RoadMap:面向自动驾驶视觉定位的轻量级语义地图(ICRA2021)

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 标题&#xff1a;RoadMap: A Light-Weight Semantic Map for Visual Localization towards Autonomous Driving 作者&#xff1a;Tong Qin, Yuxin Zheng, Tongqing Chen, Yilun Chen, and Qing Su 来源&#…

计算机图形学作业( 三):使用openGL画一个立方体,并实现平移、旋转和放缩变换

计算机图形学作业( 三):使用openGL画一个立方体,并实现平移、旋转和放缩变换 题目引入GLM库画立方体模型、观察和投影修改着色器立方体的顶点深度测试立方体变换平移旋转放缩渲染管线的理解代码题目 引入GLM库 利用 openGL 进行 3D 绘图需要用到大量的数学矩阵运算,而 Op…

一文掌握基于深度学习的自动驾驶小车开发(Pytorch实现,含完整数据和源码,树莓派+神经计算棒)

目录 一 . 基本介绍 二、模拟平台安装和基本使用 三、基于OpenCV的自动驾驶控制 3.1基于HSV空间的特定颜色区域提取 3.2基于canny算子的边缘轮廓提取 3.3感兴趣区域定位 3.4基于霍夫变换的线段检测 3.5动作控制&#xff1a;转向角 四、基于深度学习的自动驾驶控制 4.…

OpenGL坐标变换及其数学原理,两种摄像机交互模型(附源程序)

&#xfeff;&#xfeff; 实验平台&#xff1a;win7&#xff0c;VS2010 先上结果截图&#xff08;文章最后下载程序&#xff0c;解压后直接运行BIN文件夹下的EXE程序&#xff09;&#xff1a; a.鼠标拖拽旋转物体&#xff0c;类似于OGRE中的“OgreBites::CameraStyle::CS_ORB…

Python-WingIde各种调试方法

一、 本地从IDE启动文件调试 主要步骤:设置断点,F5开始调试 二、 本地从IDE外启动文件调试 1.) 从WingIDE的安装目录(默认C:\Program Files (x86)\Wing IDE 6.0)复制wingdbstub.py到被调试代码所在目录 2.) 代码中添加importwingdbstub 3.) IDE左下角设置如图 4.) 在…

图形处理单元(GPU)的演进

CPU 和 GPU 好久没有更新了&#xff0c;最近在阅读 CUDA 相关的一些论文&#xff0c;因为都是碎片化阅读&#xff0c;容易导致读过后&#xff0c;可能过一段时间又忘记掉&#xff0c;所以决定抽时间翻译翻译阅读的论文&#xff0c;一方面增强自己记忆&#xff0c;一方面与大家共…

图形学 光栅化 matlab 源代码

实验二&#xff1a;直线的光栅化算法 DDA Bresenham 实验三&#xff1a;圆的光栅化算法 编程实现两种中点画圆算法&#xff0c;第2种算法利用二阶差分方法&#xff1b; 实验四&#xff1a;多边形扫描转换算法 4.1对多边形扫描线填充算法进行简要描述&#xff0c;并给出多边形扫…

图形学入门合集1

Games101作业0 1虚拟机的使用 1.1虚拟机的安装 这里我们使用 Oracle VM VirtualBox 虚拟机。如果你使用 Windows 系统&#xff0c;你可以直接下载[链接](https://download.virtualbo%20%09%09x.org/virtualbox/6.1.4/VirtualBox-6.1.4-136177-Win.exe)&#xff0c;下载完成后…

Recorder︱图像特征检测及提取算法、基本属性、匹配方法

在做图像的研究&#xff0c;发现对图像本质、内核以及可以提取的特征方式一点儿都不懂&#xff0c;赶紧补补课。 . 一、图像常用属性 本节指的是一般来说&#xff0c;图像处理的一些角度&#xff0c;也是根据一些美图软件最为关注的一些图像属性&#xff1a; 基本属性&#…

视觉SLAM十四讲学习笔记-第三讲-相似、仿射、射影变换和eigen程序、可视化演示

专栏系列文章如下&#xff1a; 视觉SLAM十四讲学习笔记-第一讲_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-初识SLAM_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第二讲-开发环境搭建_goldqiu的博客-CSDN博客 视觉SLAM十四讲学习笔记-第三讲-旋转矩阵和E…

多视图几何三维重建实战系列之MVSNet

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 1. 概述 MVS是一种从具有一定重叠度的多视图视角中恢复场景的稠密结构的技术&#xff0c;传统方法利用几何、光学一致性构造匹配代价&#xff0c;进行匹配代价累积&#xff0c;再估计深度值。虽然传统方法有较…

一文搞懂NSCT(Nonsubsampled Contourlet)变换,matlab程序实现并讲解NSCT_TOOLBOX的使用方法

文章目录 一、前言二、NSCT理论背景三、NSCT图像表述3.1 图像变换综述3.2 非下采样的金字塔分解3.2 非下采样的方向滤波器组分解 四、NSCT的matlab程序实现五、总结5.1 NSCT现存不足5.2 致谢 一、前言 在这篇文章中我将从图像分解领域的发展方面为大家讲解NSCT的出现背景和实现…

视图几何三维重建实战系列之MVSNet

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 1. 概述 MVS是一种从具有一定重叠度的多视图视角中恢复场景的稠密结构的技术&#xff0c;传统方法利用几何、光学一致性构造匹配代价&#xff0c;进行匹配代价累积&#xff0c;再估计深度值。虽然传统方法有较…

[模板匹配霍夫变换]——模板匹配分析、霍夫变换分析

一、模板匹配分析 所谓模板匹配&#xff0c;就是在给定的图片中查找和模板最相似的区域&#xff0c;该算法的输入包括模板和图片&#xff0c;整个任务的思路就是按照滑窗的思路不断的移动模板图片&#xff0c;计算其与图像中对应区域的匹配度&#xff0c;最终将匹配度最高的区域…

计算机视觉学习第5章——多视图几何

目录 一、 外极几何 1.1 简单数据集 1.2 用Matplotlib绘制三维数据 1.3 计算F&#xff1a;八点法 1.4 外极点和外极线 二、照相机和三维结构的计算 2.1 三角部分 2.2 由三维点计算照相机矩阵 2.3 由基础矩阵计算照相机矩阵 三、多视图重建 3.1 稳健估计基础矩阵 …

Python计算机视觉——多视图几何

文章目录 第五章 多视图几何5.1 外极几何5.1.1 一个简单的数据集5.1.2 用Matplotlib绘制三维数据5.1.3 计算F&#xff1a;八点法5.1.4 外极点和外极线 5.2 照相机和三维结构的计算5.2.1 三角剖分5.2.2 由三维点计算照相机矩阵5.2.3 由基础矩阵计算照相机矩阵 5.3 多视图重建5.3…

curvelet变换的理解

一、matlab下curvelet工具包配置 首先在curvelet官方网站下载curvelet工具包&#xff0c;解压&#xff0c;其中包含了matlab与C语言两种实现的版本。 打开matlab&#xff0c;点击set path&#xff0c;选择“添加并包含子文件夹”&#xff0c;将有关的matlab代码&#xff0c;即…

java几何画板_geogebra几何画板下载

geogebra几何画板官方版是一款功能十分强大、非常专业的理科几何绘制工具&#xff0c;使用geogebra几何画板官方版您可以在上面画点、向量、线段、直线、多边形、圆锥曲线&#xff0c;甚至是函数以图像的形式呈现到您眼前。geogebra几何画板最新版是款非常不错的软件。 基本简介…

如何远程连接SQL Server数据库

一.设置客户端网络实用工具 点击“开始”&#xff0d;“程序”&#xff0c;在“Microsoft SQL Server”菜单中选择“客户端网络实用工具”。 在“别名”选项中点击“添加”。 在“服务器别名”中&#xff0c;填入您网站域名&#xff0c;在“网络库”区域中点击“TCP/IP”,在…