导航:首页 > 源码编译 > flann匹配算法

flann匹配算法

发布时间:2023-06-10 02:03:36

㈠ 什么是PCL编程

PCL(Point Cloud Library)是在吸收了前人点云相关研究基础上建立起来的大型跨平台开源C++编程库,它实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。

支持多种操作系统平台,可在Windows、Linux、Android、Mac OS X、部分嵌入式实时系统上运行。如果说OpenCV是2D信息获取与处理的结晶,那么PCL就在3D信息获取与处理上具有同等地位,PCL是BSD授权方式,可以免费进行商业和学术应用。

(1)flann匹配算法扩展阅读

PCL利用OpenMP、GPU、CUDA等先进高性能计算技术,通过并行化提高程序实时性。K近邻搜索操作的构架是基于FLANN (Fast Library for Approximate Nearest Neighbors)所实现的,速度也是目前技术中最快的。

PCL中的所有模块和算法都是通过Boost共享指针来传送数据的,因而避免了多次复制系统中已存在的数据的需要,从0.6版本开始,PCL就已经被移入到Windows,MacOS和Linux系统,并且在Android系统也已经开始投入使用,这使得PCL的应用容易移植与多方发布。

参考资料来源:网络-PCL

㈡ opencv2.4.5中cvStereoGCState在哪个模块

一、模块:
①core. 该模块定义了OpenCV的基本数据结构,包括多维数组(Multi-dimensional Array)和用于其它模块的基本函数;
②imgproc. 该模块用于图像处理(Image Processing)。它包括线性和非线性的图像滤波(Linear and Non-Linear Image Filtering)、几何图像变换(Geometrical image Transformations),包括缩放(Resize), affine and perspective warping, generic table-based remapping、颜色空间变换(Color Space Conversion)、直方图(Histograms)等;
③video. 这是一个视频分析模块,包含运动估计(Motion Estimation)、背景消除/背景差分(Background Subtraction)和物体跟踪(Object Tracking)算法;
④calib3d. 该模块包括基本的多视图集合算法(Multiple-View Geometry Algorithms)、单体和立体相机的标定(Single and Stereo Camera Calibration)、对象姿态估计(Object Pose Estimation)、双目立体匹配(Stereo Correspondence)算法和元素的三维重建(Elements of 3D Reconstruction);
⑤features2d. 包括显着特征检测器(Salient Feature Detectors)、描述符(Descriptors)和描述符匹配器(Descriptor Matchers);
⑥objdetect. 包括预定义的目标和实例的检测,如脸、眼、杯子、人以及汽车等; ⑦highgui. 该模块拥有一个简单易用的视频捕捉(Video Capturing)、图像及视频译码(Image and Video Codecs)以及简单的UI接口;
⑧gpu. 包含不同模块的GPU加速算法。
另外还有其它的辅助模块,比如FLANN以及Google的测试包、Python bindings等。

二、简介:
OpenCV(Open Source Computer Vision)是一个用于实时处理的计算机视觉函数库,它基于BSD许可证授权并且可免费用于学术研究和商业应用。它拥有C/C++、Python、和Java(仅用于Android)接口,并可在Windows、Linux、Mac和Android平台上运行。OpenCV库包含大于2500个优化算法,拥有5M的下载量和47K+的用户群体。

㈢ opencv surf算法连线颜色怎么设置一样

/**
* @file SURF_Homography
* @brief SURF detector + descriptor + FLANN Matcher + FindHomography
* @author A. Huaman
*/

#include <stdio.h>
#include <iostream>
#include <cv.h>
#include "opencv2/core/core.hpp"
#include <opencv2/opencv.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/nonfree/nonfree.hpp>

using namespace cv;
using namespace std;

#ifdef _DEBUG
#pragma comment (lib, "opencv_calib3d246d.lib")
#pragma comment (lib, "opencv_contrib246d.lib")
#pragma comment (lib,"opencv_imgproc246d.lib")
#pragma comment (lib, "opencv_core246d.lib")
#pragma comment (lib, "opencv_features2d246d.lib")
#pragma comment (lib, "opencv_flann246d.lib")
#pragma comment (lib, "opencv_gpu246d.lib")
#pragma comment (lib, "opencv_highgui246d.lib")
#pragma comment (lib, "opencv_legacy246d.lib")
#pragma comment (lib, "opencv_ml246d.lib")
#pragma comment (lib, "opencv_objdetect246d.lib")
#pragma comment (lib, "opencv_ts246d.lib")
#pragma comment (lib, "opencv_video246d.lib")
#pragma comment (lib, "opencv_nonfree246d.lib")
#else
#pragma comment (lib, "opencv_calib3d246.lib")
#pragma comment (lib, "opencv_contrib246.lib")
#pragma comment (lib, "opencv_imgproc246.lib")
#pragma comment (lib, "opencv_core246.lib")
#pragma comment (lib, "opencv_features2d246.lib")
#pragma comment (lib, "opencv_flann246.lib")
#pragma comment (lib, "opencv_gpu246.lib")
#pragma comment (lib, "opencv_highgui246.lib")
#pragma comment (lib, "opencv_legacy246.lib")
#pragma comment (lib, "opencv_ml246.lib")
#pragma comment (lib, "opencv_objdetect246.lib")
#pragma comment (lib, "opencv_ts246.lib")
#pragma comment (lib, "opencv_video246.lib")
#pragma comment (lib, "opencv_nonfree246.lib")
#endif

int main()
{
initMole_nonfree();//初始化模块,使用SIFT或SURF时用到
Ptr<FeatureDetector> detector = FeatureDetector::create( "SURF" );//创建SIFT特征检测器,可改成SURF/ORB
Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SURF" );//创建特征向量生成器,可改成SURF/ORB
Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器
if( detector.empty() || descriptor_extractor.empty() )
cout<<"fail to create detector!";

//读入图像
Mat img1 = imread("1.jpg");
Mat img2 = imread("2.jpg");

//特征点检测
double t = getTickCount();//当前滴答数
vector<KeyPoint> m_LeftKey,m_RightKey;
detector->detect( img1, m_LeftKey );//检测img1中的SIFT特征点,存储到m_LeftKey中
detector->detect( img2, m_RightKey );
cout<<"图像1特征点个数:"<<m_LeftKey.size()<<endl;
cout<<"图像2特征点个数:"<<m_RightKey.size()<<endl;

//根据特征点计算特征描述子矩阵,即特征向量矩阵
Mat descriptors1,descriptors2;
descriptor_extractor->compute( img1, m_LeftKey, descriptors1 );
descriptor_extractor->compute( img2, m_RightKey, descriptors2 );
t = ((double)getTickCount() - t)/getTickFrequency();
cout<<"SIFT算法用时:"<<t<<"秒"<<endl;

cout<<"图像1特征描述矩阵大小:"<<descriptors1.size()
<<",特征向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl;
cout<<"图像2特征描述矩阵大小:"<<descriptors2.size()
<<",特征向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl;

//画出特征点
Mat img_m_LeftKey,img_m_RightKey;
drawKeypoints(img1,m_LeftKey,img_m_LeftKey,Scalar::all(-1),0);
drawKeypoints(img2,m_RightKey,img_m_RightKey,Scalar::all(-1),0);
//imshow("Src1",img_m_LeftKey);
//imshow("Src2",img_m_RightKey);

//特征匹配
vector<DMatch> matches;//匹配结果
descriptor_matcher->match( descriptors1, descriptors2, matches );//匹配两个图像的特征矩阵
cout<<"Match个数:"<<matches.size()<<endl;

//计算匹配结果中距离的最大和最小值
//距离是指两个特征向量间的欧式距离,表明两个特征的差异,值越小表明两个特征点越接近
double max_dist = 0;
double min_dist = 100;
for(int i=0; i<matches.size(); i++)
{
double dist = matches[i].distance;
if(dist < min_dist) min_dist = dist;
if(dist > max_dist) max_dist = dist;
}
cout<<"最大距离:"<<max_dist<<endl;
cout<<"最小距离:"<<min_dist<<endl;

//筛选出较好的匹配点
vector<DMatch> goodMatches;
for(int i=0; i<matches.size(); i++)
{
if(matches[i].distance < 0.2 * max_dist)
{
goodMatches.push_back(matches[i]);
}
}
cout<<"goodMatch个数:"<<goodMatches.size()<<endl;

//画出匹配结果
Mat img_matches;
//红色连接的是匹配的特征点对,绿色是未匹配的特征点
drawMatches(img1,m_LeftKey,img2,m_RightKey,goodMatches,img_matches,
Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);

imshow("MatchSIFT",img_matches);
IplImage result=img_matches;

waitKey(0);

//RANSAC匹配过程
vector<DMatch> m_Matches=goodMatches;
// 分配空间
int ptCount = (int)m_Matches.size();
Mat p1(ptCount, 2, CV_32F);
Mat p2(ptCount, 2, CV_32F);

// 把Keypoint转换为Mat
Point2f pt;
for (int i=0; i<ptCount; i++)
{
pt = m_LeftKey[m_Matches[i].queryIdx].pt;
p1.at<float>(i, 0) = pt.x;
p1.at<float>(i, 1) = pt.y;

pt = m_RightKey[m_Matches[i].trainIdx].pt;
p2.at<float>(i, 0) = pt.x;
p2.at<float>(i, 1) = pt.y;
}

// 用RANSAC方法计算F
Mat m_Fundamental;
vector<uchar> m_RANSACStatus; // 这个变量用于存储RANSAC后每个点的状态
findFundamentalMat(p1, p2, m_RANSACStatus, FM_RANSAC);

// 计算野点个数

int OutlinerCount = 0;
for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] == 0) // 状态为0表示野点
{
OutlinerCount++;
}
}
int InlinerCount = ptCount - OutlinerCount; // 计算内点
cout<<"内点数为:"<<InlinerCount<<endl;

// 这三个变量用于保存内点和匹配关系
vector<Point2f> m_LeftInlier;
vector<Point2f> m_RightInlier;
vector<DMatch> m_InlierMatches;

m_InlierMatches.resize(InlinerCount);
m_LeftInlier.resize(InlinerCount);
m_RightInlier.resize(InlinerCount);
InlinerCount=0;
float inlier_minRx=img1.cols; //用于存储内点中右图最小横坐标,以便后续融合

for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] != 0)
{
m_LeftInlier[InlinerCount].x = p1.at<float>(i, 0);
m_LeftInlier[InlinerCount].y = p1.at<float>(i, 1);
m_RightInlier[InlinerCount].x = p2.at<float>(i, 0);
m_RightInlier[InlinerCount].y = p2.at<float>(i, 1);
m_InlierMatches[InlinerCount].queryIdx = InlinerCount;
m_InlierMatches[InlinerCount].trainIdx = InlinerCount;

if(m_RightInlier[InlinerCount].x<inlier_minRx) inlier_minRx=m_RightInlier[InlinerCount].x; //存储内点中右图最小横坐标

InlinerCount++;
}
}

// 把内点转换为drawMatches可以使用的格式
vector<KeyPoint> key1(InlinerCount);
vector<KeyPoint> key2(InlinerCount);
KeyPoint::convert(m_LeftInlier, key1);
KeyPoint::convert(m_RightInlier, key2);

// 显示计算F过后的内点匹配
Mat OutImage;
drawMatches(img1, key1, img2, key2, m_InlierMatches, OutImage);
cvNamedWindow( "Match features", 1);
cvShowImage("Match features", &IplImage(OutImage));
waitKey(0);

cvDestroyAllWindows();

//矩阵H用以存储RANSAC得到的单应矩阵
Mat H = findHomography( m_LeftInlier, m_RightInlier, RANSAC );

//存储左图四角,及其变换到右图位置
std::vector<Point2f> obj_corners(4);
obj_corners[0] = Point(0,0); obj_corners[1] = Point( img1.cols, 0 );
obj_corners[2] = Point( img1.cols, img1.rows ); obj_corners[3] = Point( 0, img1.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);

//画出变换后图像位置
Point2f offset( (float)img1.cols, 0);
line( OutImage, scene_corners[0]+offset, scene_corners[1]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[1]+offset, scene_corners[2]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[2]+offset, scene_corners[3]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[3]+offset, scene_corners[0]+offset, Scalar( 0, 255, 0), 4 );
imshow( "Good Matches & Object detection", OutImage );

waitKey(0);
imwrite("warp_position.jpg",OutImage);

int drift = scene_corners[1].x; //储存偏移量

㈣ 求在vs2010和opencv 2.2环境下 sift匹配图像源码,求大神。

#include<ctime>

#include<iostream>

#include"opencv2/core/core.hpp"

#include"opencv2/features2d/features2d.hpp"

#include"opencv2/highgui/highgui.hpp"

#include"opencv2/calib3d/calib3d.hpp"

usingnamespacecv;

usingnamespacestd;

voidreadme();

//主函数

intmain(intargc,char*argv[])

{

if(argc>3)

{

readme();

return-1;

}

//默认参数

if(argc<3)

{

argv[1]="box.png";

argv[2]="box_in_scene.png";

}

//加载图像

Matimg_object=imread(argv[1],CV_LOAD_IMAGE_GRAYSCALE);

Matimg_scene=imread(argv[2],CV_LOAD_IMAGE_GRAYSCALE);

if(!img_object.data||!img_scene.data)

{

std::cout<<"--(!)Errorreadingimages"<<std::endl;

return-1;

}

doublebegin=clock();

//第一步:用SIFT算子检测关键点

SiftFeatureDetectordetector;//构造函数采用默认的

std::vector<KeyPoint>keypoints_object,keypoints_scene;//构造2个专门由点组成的点向量用来存储特征点

detector.detect(img_object,keypoints_object);//将img_object图像中检测到的特征点存储起来放在keypoints_object中

detector.detect(img_scene,keypoints_scene);//同理

//在图像中画出特征点

Matimg_keypoints_object,img_keypoints_scene;

//先在内存中绘制

drawKeypoints(img_object,keypoints_object,img_keypoints_object,Scalar::all(-1),DrawMatchesFlags::DEFAULT);//在内存中画出特征点

drawKeypoints(img_scene,keypoints_scene,img_keypoints_scene,Scalar::all(-1),DrawMatchesFlags::DEFAULT);

//再显示

imshow("sift_keypoints_object",img_keypoints_object);

imshow("sift_keypoints_scene",img_keypoints_scene);

//第二步:计算特征向量

;//定义描述子对象

Matdescriptors_1,descriptors_2;//存放特征向量的矩阵

//计算特征向量

extractor.compute(img_object,keypoints_object,descriptors_1);

extractor.compute(img_scene,keypoints_scene,descriptors_2);

//第三步,用FLANN进行匹配特征向量

FlannBasedMatchermatcher;//定义一个FlannBasedMatcher对象

std::vector<DMatch>matches;

matcher.match(descriptors_1,descriptors_2,matches);

doublemax_dist=0;

doublemin_dist=100;

//计算特征点间的最大最小距离

for(inti=0;i<descriptors_1.rows;i++)

{

doubledist=matches[i].distance;

if(dist<min_dist)min_dist=dist;

if(dist>max_dist)max_dist=dist;

}

printf("--Maxdist:%f ",max_dist);

printf("--Mindist:%f ",min_dist);

//只保留好的匹配:特征点距离小于3倍最小距离

std::vector<DMatch>good_matches;

for(inti=0;i<descriptors_1.rows;i++)

{

if(matches[i].distance<3*min_dist)

{

good_matches.push_back(matches[i]);

}

}

//在内存中绘制保留的好的匹配

Matimg_matches;

drawMatches(img_object,keypoints_object,img_scene,keypoints_scene,

good_matches,img_matches,Scalar::all(-1),Scalar::all(-1),

vector<char>(),DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

//在场景中定位目标图像

std::vector<Point2f>obj;

std::vector<Point2f>scene;

std::cout<<"good_matches.size():"<<good_matches.size()<<" ";

for(inti=0;i<good_matches.size();i++)

{

//从好的匹配中找到特征点

obj.push_back(keypoints_object[good_matches[i].queryIdx].pt);

scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt);

}

//基于匹配的关键点找出相应的变换

cv::MatH=cv::findHomography(cv::Mat(obj),cv::Mat(scene),CV_RANSAC);

//找到目标的角点

std::vector<Point2f>obj_corners(4);

obj_corners[0]=cvPoint(0,0);

obj_corners[1]=cvPoint(img_object.cols,0);

obj_corners[2]=cvPoint(img_object.cols,img_object.rows);

obj_corners[3]=cvPoint(0,img_object.rows);

std::vector<Point2f>scene_corners(4);

//映射点群,在场景中获取目标的坐标

cv::perspectiveTransform(cv::Mat(obj_corners),cv::Mat(scene_corners),H);

//目标的角点之间连线(框出目标)

line(img_matches,scene_corners[0]+Point2f(img_object.cols,0),scene_corners[1]+Point2f(img_object.cols,0),Scalar(0,255,0),4);

line(img_matches,scene_corners[1]+Point2f(img_object.cols,0),scene_corners[2]+Point2f(img_object.cols,0),Scalar(0,255,0),4);

line(img_matches,scene_corners[2]+Point2f(img_object.cols,0),scene_corners[3]+Point2f(img_object.cols,0),Scalar(0,255,0),4);

line(img_matches,scene_corners[3]+Point2f(img_object.cols,0),scene_corners[0]+Point2f(img_object.cols,0),Scalar(0,255,0),4);

//显示保留的好的匹配

imshow("GoodMatches&Objectdetection-SIFT",img_matches);

imwrite("GoodMatches&Objectdetection-SIFT.png",img_matches);

doubleend=clock();

cout<<" SURF-elapsedtimeis:"<<(end-begin)/CLOCKS_PER_SEC*1000<<"ms ";

waitKey(0);

return0;

}

/**

*@函数readme

*/

voidreadme()

{

std::cout<<"Usage:./cv_sift_demo<img1><img2>"<<std::endl;

}


box_in_scene.png

㈤ 使用OpenCV和Python进行图像拼接

么是图像拼接呢?简单来说,对于输入应该有一组图像,输出是合成图像。同时,必须保留图像之间的逻辑流。

首先让我们了解图像拼接的概念。基本上,如果你想捕捉一个大的场景,你的相机只能提供一个特定分辨率的图像(如:640×480),这当然不足以捕捉大的全景。所以,我们可以做的是捕捉整个场景的多个图像,然后把所有的碎片放在一起,形成一个大的图像。这些有序的照片被称为全景。获取多幅图像并将其转换成全景图的整个过程称为图像拼接。

首先,需要安装opencv 3.4.2.16。

接下来我们将导入我们将在Python代码中使用的库:

在我们的教程中,我们将拍摄这张精美的照片,我们会将其分成两张左右两张照片,然后我们会尝试拍摄相同或非常相似的照片。

因此,我将此图像切成两个图像,它们会有某种重叠区域:

在此,我们将列出我们应采取的步骤,以取得最终的结果:

因此,从第一步开始,我们将导入这两个图像并将它们转换为灰度,如果您使用的是大图像,我建议您使用cv2.resize,因为如果您使用较旧的计算机,它可能会非常慢并且需要很长时间。如果要调整图像大小,即调整50%,只需将fx = 1更改为fx = 0.5即可。

我们还需要找出两幅图像中匹配的特征。我们将使用opencv_contrib的SIFT描述符。SIFT (Scale constant Feature Transform)是一种非常强大的OpenCV算法。这些最匹配的特征作为拼接的基础。我们提取两幅图像的关键点和sift描述符如下:

kp1和kp2是关键点,des1和des2是图像的描述符。如果我们用特征来画这幅图,它会是这样的:

左边的图像显示实际图像。右侧的图像使用SIFT检测到的特征进行注释:

一旦你有了两个图像的描述符和关键点,我们就会发现它们之间的对应关系。我们为什么要这么做?为了将任意两个图像连接成一个更大的图像,我们必须找到重叠的点。这些重叠的点会让我们根据第一幅图像了解第二幅图像的方向。根据这些公共点,我们就能知道第二幅图像是大是小还是旋转后重叠,或者缩小/放大后再fitted。所有此类信息的产生是通过建立对应关系来实现的。这个过程称为registration。

对于匹配图像,可以使用opencv提供的FLANN或BFMatcher方法。我会写两个例子证明我们会得到相同的结果。两个示例都匹配两张照片中更相似的特征。当我们设置参数k = 2时,这样我们就要求knnMatcher为每个描述符给出2个最佳匹配。“matches”是列表的列表,其中每个子列表由“k”个对象组成。以下是Python代码:

FLANN匹配代码:

BFMatcher匹配代码:

通常在图像中,图像的许多地方可能存在许多特征。所以我们过滤掉所有的匹配来得到最好的。因此我们使用上面得到的前2个匹配项进行比值检验。如果下面定义的比值大于指定的比值,则考虑匹配。

现在我们定义在图像上绘制线条的参数,并给出输出以查看当我们在图像上找到所有匹配时的样子:

这是输出的匹配图像:

这部分完整Python代码:

因此,一旦我们获得了图像之间的最佳匹配,我们的下一步就是计算单应矩阵。如前所述,单应矩阵将与最佳匹配点一起使用,以估计两个图像内的相对方向变换。

在OpenCV中估计单应性是一项简单的任务,只需一行代码:

在开始编码拼接算法之前,我们需要交换图像输入。所以img_现在会取右图像img会取左图像。

那么让我们进入拼接编码:

因此,首先,我们将最小匹配条件count设置为10(由MIN_MATCH_COUNT定义),并且只有在匹配良好的匹配超出所需匹配时才进行拼接。否则,只需显示一条消息,说明匹配不够。

因此,在if语句中,我们将关键点(从匹配列表)转换为findHomography()函数的参数。

只需在这段代码中讨论cv2.imshow(“original_image_overlapping.jpg”,img2),我们就会显示我们收到的图像重叠区域:

因此,一旦我们建立了单应性,我们需要扭曲视角,我们将以下单应矩阵应用于图像:

所以我们使用如下:

在上面两行Python代码中,我们从两个给定的图像中获取重叠区域。然后在“dst”中我们只接收到没有重叠的图像的右侧,因此在第二行代码中我们将左侧图像放置到最终图像。所以在这一点上我们完全拼接了图像:

剩下的就是去除图像的黑色,所以我们将编写以下代码来从所有图像边框中删除黑边:

这是我们调用修剪边界的最终定义函数,同时我们在屏幕上显示该图像。如果您愿意,也可以将其写入磁盘:

使用上面的Python代码,我们将首先收到原始图片:

这是完整的最终代码:

在本教程中,我们学习了如何使用OpenCV执行图像拼接和全景构造,并编写了最终的图像拼接代码。

我们的图像拼接算法需要四个主要步骤:检测关键点和提取局部不变描述符; 获得图像之间的匹配描述符; 应用RANSAC估计单应矩阵; 使用单应矩阵应用warping transformation。

当仅为两个图像构建全景图时,该算法在实践中工作良好。

阅读全文

与flann匹配算法相关的资料

热点内容
dvd光盘存储汉子算法 浏览:758
苹果邮件无法连接服务器地址 浏览:963
phpffmpeg转码 浏览:672
长沙好玩的解压项目 浏览:145
专属学情分析报告是什么app 浏览:564
php工程部署 浏览:833
android全屏透明 浏览:737
阿里云服务器已开通怎么办 浏览:803
光遇为什么登录时服务器已满 浏览:302
PDF分析 浏览:486
h3c光纤全工半全工设置命令 浏览:143
公司法pdf下载 浏览:383
linuxmarkdown 浏览:350
华为手机怎么多选文件夹 浏览:683
如何取消命令方块指令 浏览:350
风翼app为什么进不去了 浏览:779
im4java压缩图片 浏览:362
数据查询网站源码 浏览:151
伊克塞尔文档怎么进行加密 浏览:893
app转账是什么 浏览:163