仿射變換詳解 warpAffine_第1頁
仿射變換詳解 warpAffine_第2頁
仿射變換詳解 warpAffine_第3頁
仿射變換詳解 warpAffine_第4頁
仿射變換詳解 warpAffine_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

仿射變換詳解warpAffine今天遇到一個問題是關(guān)于仿射變換的,但是由于沒有將仿射變換的具體原理型明白,看別人的代碼看的很費(fèi)解,最后終于在師兄的幫助下將原理弄明白了,我覺得最重要的是理解仿射變換可以看成是幾種簡單變換的復(fù)合實(shí)現(xiàn),具體實(shí)現(xiàn)形式即將幾種簡單變換的變換矩陣M相乘,這樣就很容易理解啦

定義:仿射變換的功能是從二維坐標(biāo)到二維坐標(biāo)之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的復(fù)合來實(shí)現(xiàn),包括平移,縮放,翻轉(zhuǎn),旋轉(zhuǎn)和剪切。這類變換可以用一個3*3的矩陣M來表示,其最后一行為(0,0,1)。該變換矩陣將原坐標(biāo)為(x,y)變換為新坐標(biāo)(x',y'),即\o"OpenCV知識庫"OpenCV中相應(yīng)的函數(shù)是:void

warpAffine(InputArray

src,OutputArray

dst,InputArray

M,Size

dsize,int

flags=INTER_LINEAR,int

borderMode=BORDER_CONSTANT,constScalar&

borderValue=Scalar())\o"Permalinktothisdefinition"?Parameters:src

–inputimage.dst

–outputimagethathasthesize

dsize

andthesametypeas

src

.M

transformationmatrix,最重要的東東了,本文中著重講M的構(gòu)造dsize

–sizeoftheoutputimage.ansformation(

).borderMode

–pixelextrapolationmethod(see

\o"intborderInterpolate(intp,intlen,intborderType)"borderInterpolate());when

borderMode=BORDER_TRANSPARENT

,itmeansthatthepixelsinthedestinationimagecorrespondingtothe“outliers”inthesourceimagearenotmodifiedbythefunction.borderValue

–valueusedincaseofaconstantborder;bydefault,itis0.

下面介紹一些典型的仿射變換:(1)平移,將每一點(diǎn)移到到(x+t,y+t),變換矩陣為(2)縮放變換

將每一點(diǎn)的橫坐標(biāo)放大或縮小sx倍,縱坐標(biāo)放大(縮小)到sy倍,變換矩陣為(3)旋轉(zhuǎn)變換原點(diǎn):目標(biāo)圖形圍繞原點(diǎn)順時針旋轉(zhuǎn)Θ弧度,變換矩陣為(4)旋轉(zhuǎn)變換

:目標(biāo)圖形以(x,y)為軸心順時針旋轉(zhuǎn)θ弧度,變換矩陣為

相當(dāng)于兩次平移與一次原點(diǎn)旋轉(zhuǎn)變換的復(fù)合,即先將軸心(x,y)移到到原點(diǎn),然后做旋轉(zhuǎn)變換,最后將圖片的左上角置為圖片的原點(diǎn),即有的人可能會說為什么這么復(fù)雜呢,那是因?yàn)樵趏pencv的圖像處理中,所有對圖像的處理都是從原點(diǎn)進(jìn)行的,而圖像的原點(diǎn)默認(rèn)為圖像的左上角,而我們對圖像作旋轉(zhuǎn)處理時一般以圖像的中點(diǎn)為軸心,因此就需要做如下處理

如果你覺得這樣很麻煩,可以使用opencv中自帶的Mat

getRotationMatrix2D(Point2fcenter,doubleangle,doublescale)函數(shù)獲得變換矩陣M,center:旋轉(zhuǎn)中心angle:旋轉(zhuǎn)弧度,一定要將角度轉(zhuǎn)換成弧度scale:縮放尺度它得到的矩陣是:

其中α=scale*cos(angle),β=scale

*sing(angle)

,(center.x,center.y)表示旋轉(zhuǎn)軸心但是不得不說opencv的文檔以及相關(guān)書籍中都把這個矩陣寫錯了,如下:建議大家自己通過下式驗(yàn)證一下,即首先將軸心(x,y)移到原點(diǎn),然后做旋轉(zhuǎn)平綻放變換,最后再將圖像的左上角轉(zhuǎn)換為原點(diǎn)沒有去研究該函數(shù)的源碼,不曉得源碼中到底怎么寫的,但是在別人的博客中看到這個函數(shù)貌似需要修正

opencv中還有一個函數(shù):Mat

getAffineTransform(InputArray

src,InputArray

dst)\o"Permalinktothisdefinition"?它通過三組點(diǎn)對就可以獲得它們之間的仿射變換,如果我們在一組圖像變換中知道變換后的三組點(diǎn),那么我們就可以利用該函數(shù)求得變換矩陣,然后對整張圖片進(jìn)行仿射變換還有一種與仿射變換經(jīng)?;煜淖儞Q為透視變換,透視變換需要四組點(diǎn)對才能確定變換矩陣,由于仿射變換保持“平直性”與“平行性”,因此只需要三組點(diǎn)對,而透視變換沒有這種約束,故需要四組點(diǎn)對

warpPerspective函數(shù)主要作用:對圖像進(jìn)行透視變換,就是變形函數(shù)的調(diào)用形式:C++:

void

warpPerspective(InputArray

src,OutputArray

dst,InputArray

M,Size

dsize,int

flags=INTER_LINEAR,int

borderMode=BORDER_CONSTANT,constScalar&

borderValue=Scalar())參數(shù)詳解:InputArray

src:輸入的圖像OutputArray

dst:輸出的圖像InputArray

M:透視變換的矩陣Size

dsize:輸出圖像的大小int

flags=INTER_LINEAR:輸出圖像的插值方法,combinationofinterpolationmethods(INTER_LINEAR

or

INTER_NEAREST)andtheoptionalflagWARP_INVERSE_MAP,thatsets

M

astheinversetransformation(

)int

borderMode=BORDER_CONSTANT:圖像邊界的處理方式constScalar&

borderValue=Scalar():邊界的顏色設(shè)置,一般默認(rèn)是0函數(shù)原理:透視變換(PerspectiveTransformation)是將圖片投影到一個新的視平面(ViewingPlane),也稱作投影映射(ProjectiveMapping)。通用的變換公式為:u,v是原始圖片左邊,對應(yīng)得到變換后的圖片坐標(biāo)x,y,其中。

變換矩陣可以拆成4部分,表示線性變換,比如scaling,shearing和ratotion。用于平移,產(chǎn)生透視變換。所以可以理解成仿射等是透視變換的特殊形式。經(jīng)過透視變換之后的圖片通常不是平行四邊形(除非映射視平面和原來平面平行的情況)。重寫之前的變換公式可以得到:所以,已知變換對應(yīng)的幾個點(diǎn)就可以求取變換公式。反之,特定的變換公式也能新的變換后的圖片。簡單的看一個正方形到四邊形的變換:

變換的4組對應(yīng)點(diǎn)可以表示成:根據(jù)變換公式得到:定義幾個輔助變量:都為0時變換平面與原來是平行的,可以得到:不為0時,得到:求解出的變換矩陣就可以將一個正方形變換到四邊形。反之,四邊形變換到正方形也是一樣的。于是,我們通過兩次變換:四邊形變換到正方形+正方形變換到四邊形就可以將任意一個四邊形變換到另一個四邊形。

opencv代碼:[cpp]

\o"viewplain"viewplain\o"copy"copy#include<cv.h>

#include<highgui.h>

#pragma

comment(lib,

"cv.lib")

#pragma

comment(lib,

"cxcore.lib")

#pragma

comment(lib,

"highgui.lib")

int

main()

{

CvPoint2D32f

srcTri[4],

dstTri[4];

CvMat*

warp_mat

=

cvCreateMat

(3,

3,

CV_32FC1);

IplImage*

src

=

NULL;

IplImage*

dst

=

NULL;

src

=

cvLoadImage

("test.png",

1);

dst

=

cvCloneImage

(src);

dst->origin

=

src->origin;

cvZero

(dst);

srcTri[0].x

=

0;

srcTri[0].y

=

0;

srcTri[1].x

=

src->width

-

1;

srcTri[1].y

=

0;

srcTri[2].x

=

0;

srcTri[2].y

=

src->height

-

1;

srcTri[3].x

=

src->width

-

1;

srcTri[3].y

=

src->height

-

1;

dstTri[0].x

=

src->width

*

0.05;

dstTri[0].y

=

src->height

*

0.33;

dstTri[1].x

=

src->width

*

0.9;

dstTri[1].y

=

src->height

*

0.25;

dstTri[2].x

=

src->width

*

0.2;

dstTri[2].y

=

src->height

*

0.7;

dstTri[3].x

=

src->width

*

0.8;

dstTri[3].y

=

src->height

*

0.9;

cvGetPerspectiveTransform

(srcTri,

dstTri,

warp_mat);

cvWarpPerspective

(src,

dst,

warp_mat);

cvNamedWindow("src",

1);

cvShowImage("src",

src);

cvNamedWindow

("Affine_Transform",

1);

cvShowImage

("Affine_Transform",

dst);

cvWaitKey

(0);

cvReleaseImage

(&src);

cvReleaseImage

(&dst);

cvReleaseMat

(&warp_mat);

return

0;

}

今天遇到一個問題是關(guān)于仿射變換的,但是由于沒有將仿射變換的具體原理型明白,看別人的代碼看的很費(fèi)解,最后終于在師兄的幫助下將原理弄明白了,我覺得最重要的是理解仿射變換可以看成是幾種簡單變換的復(fù)合實(shí)現(xiàn),具體實(shí)現(xiàn)形式即將幾種簡單變換的變換矩陣M相乘,這樣就很容易理解啦

定義:仿射變換的功能是從二維坐標(biāo)到二維坐標(biāo)之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的復(fù)合來實(shí)現(xiàn),包括平移,縮放,翻轉(zhuǎn),旋轉(zhuǎn)和剪切。這類變換可以用一個3*3的矩陣M來表示,其最后一行為(0,0,1)。該變換矩陣將原坐標(biāo)為(x,y)變換為新坐標(biāo)(x',y'),即opencv中相應(yīng)的函數(shù)是:void

warpAffine(InputArray

src,OutputArray

dst,InputArray

M,Size

dsize,int

flags=INTER_LINEAR,int

borderMode=BORDER_CONSTANT,constScalar&

borderValue=Scalar())\o"Permalinktothisdefinition"?Parameters:src

–inputimage.dst

–outputimagethathasthesize

dsize

andthesametypeas

src

.M

transformationmatrix,最重要的東東了,本文中著重講M的構(gòu)造dsize

–sizeoftheoutputimage.flags

–combinationofinterpolationmethods(see

\o"voidresize(InputArraysrc,OutputArraydst,Sizedsize,doublefx,doublefy,intinterpolation)"resize()

)andtheoptionalflag

WARP_INVERSE_MAP

thatmeansthat

M

istheinversetransformation(

).borderMode

–pixelextrapolationmethod(see

\o"intborderInterpolate(intp,intlen,intborderType)"borderInterpolate());when

borderMode=BORDER_TRANSPARENT

,itmeansthatthepixelsinthedestinationimagecorrespondingtothe“outliers”inthesourceimagearenotmodifiedbythefunction.borderValue

–valueusedincaseofaconstantborder;bydefault,itis0.

下面介紹一些典型的仿射變換:(1)平移,將每一點(diǎn)移到到(x+t,y+t),變換矩陣為(2)縮放變換

將每一點(diǎn)的橫坐標(biāo)放大或縮小sx倍,縱坐標(biāo)放大(縮?。┑絪y倍,變換矩陣為(3)旋轉(zhuǎn)變換原點(diǎn):目標(biāo)圖形圍繞原點(diǎn)順時針旋轉(zhuǎn)Θ弧度,變換矩陣為(4)旋轉(zhuǎn)變換

:目標(biāo)圖形以(x,y)為軸心順時針旋轉(zhuǎn)θ弧度,變換矩陣為

相當(dāng)于兩次平移與一次原點(diǎn)旋轉(zhuǎn)變換的復(fù)合,即先將軸心(x,y)移到到原點(diǎn),然后做旋轉(zhuǎn)變換,最后將圖片的左上角置為圖片的原點(diǎn),即有的人可能會說為什么這么復(fù)雜呢,那是因?yàn)樵趏pencv的圖像處理中,所有對圖像的處理都是從原點(diǎn)進(jìn)行的,而圖像的原點(diǎn)默認(rèn)為圖像的左上角,而我們對圖像作旋轉(zhuǎn)處理時一般以圖像的中點(diǎn)為軸心,因此就需要做如下處理

如果你覺得這樣很麻煩,可以使用opencv中自帶的Mat

getRotationMatrix2D(Point2fcenter,doubleangle,doublescale)函數(shù)獲得變換矩陣M,center:旋轉(zhuǎn)中心angle:旋轉(zhuǎn)弧度,一定要將角度轉(zhuǎn)換成弧度scale:縮放尺度它得到的矩陣是:

opencv中還有一個函數(shù):Mat

getAffineTransform(InputArray

src,InputArray

dst)\o"Permalinktothisdefinition"?它通過三組點(diǎn)對就可以獲得它們之間的仿射變換,如果我們在一組圖像變換中知道變換后的三組點(diǎn),那么我們就可以利用該函數(shù)求得變換矩陣,然后對整張圖片進(jìn)行仿射變換還有一種與仿射變換經(jīng)?;煜淖儞Q為透視變換,透視變換需要四組點(diǎn)對才能確定變換矩陣,由于仿射變換保持“平直性”與“平行性”,因此只需要三組點(diǎn)對,而透視變換沒有這種約束,故需要四組點(diǎn)對

本文將openCV中的RANSAC代碼全部挑選出來,進(jìn)行分析和講解,以便大家更好的理解RANSAC\o"算法與數(shù)據(jù)結(jié)構(gòu)知識庫"算法。代碼我都試過,可以直接運(yùn)行。在計(jì)算機(jī)視覺和圖像處理等很多領(lǐng)域,都需要用到RANSAC算法。openCV中也有封裝好的RANSAC算法,以便于人們使用。關(guān)于RANSAC算法的一些應(yīng)用,可以看我的另一篇博客:利用SIFT和RANSAC算法(openCV框架)實(shí)現(xiàn)物體的檢測與定位,并求出變換矩陣(findFundamentalMat和findHomography的比較)但是前幾天師弟在使用openCV自帶的RANSAC算法時,發(fā)現(xiàn)實(shí)驗(yàn)的運(yùn)行時間并不會隨著輸入數(shù)據(jù)的增加而增加,感覺和理論上的不太相符。所以我就花了點(diǎn)時間,把openCV中關(guān)于RANSAC的源代碼全部復(fù)制出來研究了一下。以便我們更加清晰的了解RANSAC算法的實(shí)際運(yùn)行過程。首先看兩個類?//模型估計(jì)的基類,提供了估計(jì)矩陣的各種虛函數(shù)//置信度設(shè)為0。99循環(huán)次數(shù)設(shè)置為了2000classCvModelEstimator2{public:

CvModelEstimator2(int_modelPoints,CvSize_modelSize,int_maxBasicSolutions);

virtual~CvModelEstimator2();

virtualintrunKernel(constCvMat*m1,constCvMat*m2,CvMat*model)=0;

//virtualboolrunLMeDS(constCvMat*m1,constCvMat*m2,CvMat*model,

//CvMat*mask,doubleconfidence=0.99,intmaxIters=2000);

virtualboolrunRANSAC(constCvMat*m1,constCvMat*m2,CvMat*model,

CvMat*mask,doublethreshold,

doubleconfidence=0.99,intmaxIters=2000);

virtualboolrefine(constCvMat*,constCvMat*,CvMat*,int){returntrue;}

//virtualvoidsetSeed(int64seed);

protected:

virtualvoidcomputeReprojError(constCvMat*m1,constCvMat*m2,

constCvMat*model,CvMat*error)=0;

virtualintfindInliers(constCvMat*m1,constCvMat*m2,

constCvMat*model,CvMat*error,

CvMat*mask,doublethreshold);

virtualboolgetSubset(constCvMat*m1,constCvMat*m2,

CvMat*ms1,CvMat*ms2,intmaxAttempts=1000);

virtualboolcheckSubset(constCvMat*ms1,intcount);

CvRNGrng;

intmodelPoints;

CvSizemodelSize;

intmaxBasicSolutions;

boolcheckPartialSubsets;};//單應(yīng)矩陣估計(jì)的子類classCvHomographyEstimator:publicCvModelEstimator2{public:

CvHomographyEstimator(intmodelPoints);

virtualintrunKernel(constCvMat*m1,constCvMat*m2,CvMat*model);

virtualboolrefine(constCvMat*m1,constCvMat*m2,

CvMat*model,intmaxIters);

protected:

virtualvoidcomputeReprojError(constCvMat*m1,constCvMat*m2,

constCvMat*model,CvMat*error);};上面的兩個類中,CvModelEstimator2是一個基類,從名字就可以看出,這個類是用來估計(jì)模型的??梢钥吹嚼锩嫣峁┝嗽S多虛函數(shù),這些函數(shù)有許多,比如runRANSAC是利用RANSAC方法計(jì)算單應(yīng)矩陣,而runLMeDS是利用LMeDS方法計(jì)算單應(yīng)矩陣,我們這里僅僅講解RANSAC方法,所以其他不需要的內(nèi)容我就直接注釋掉了CvHomographyEstimator繼承自CvModelEstimator2,同樣的,從名字也就可以看出,這個類使用來估計(jì)單應(yīng)矩陣的。接下來是兩個類的構(gòu)造函數(shù)和析構(gòu)函數(shù),這個沒啥好說的了,基本都是默認(rèn)的。?4本范例的代碼主要都是

學(xué)習(xí)OpenCV——通過KeyPoints進(jìn)行目標(biāo)定位這篇博客提供的,然后在它的基礎(chǔ)上稍加修改,檢測keypoints點(diǎn)的檢測器是SURF,獲取描述子也是用到SURF來描述,而用到的匹配器是FlannBased,匹配的方式是Knn方式,最后通過findHomography尋找單映射矩陣,perspectiveTransform獲得最終的目標(biāo),在這個過程中還通過單映射矩陣來進(jìn)一步去除偽匹配,這里只是貼出代碼和代碼解析,至于原理還沒弄得特別明白,希望接下來可以繼續(xù)學(xué)習(xí),學(xué)懂了\o"算法與數(shù)據(jù)結(jié)構(gòu)知識庫"算法原理再來補(bǔ)充。1、代碼實(shí)現(xiàn)[cpp]

\o"viewplain"viewplain

\o"copy"copy

<span

style="font-size:18px;">#include

"stdafx.h"

#include

"opencv2/opencv.hpp"

#include

<vector>

#include

<iostream>

using

namespace

cv;

using

namespace

std;

Mat

src,frameImg;

int

width;

int

height;

vector<Point>

srcCorner(4);

vector<Point>

dstCorner(4);

static

bool

createDetectorDescriptorMatcher(

const

string&

detectorType,

const

string&

descriptorType,

const

string&

matcherType,

Ptr<FeatureDetector>&

featureDetector,

Ptr<DescriptorExtractor>&

descriptorExtractor,

Ptr<DescriptorMatcher>&

descriptorMatcher

)

{

cout

<<

"<

Creating

feature

detector,

descriptor

extractor

and

descriptor

matcher

..."

<<

endl;

if

(detectorType=="SIFT"||detectorType=="SURF")

initModule_nonfree();

featureDetector

=

FeatureDetector::create(

detectorType

);

descriptorExtractor

=

DescriptorExtractor::create(

descriptorType

);

descriptorMatcher

=

DescriptorMatcher::create(

matcherType

);

cout

<<

">"

<<

endl;

bool

isCreated

=

!(

featureDetector.empty()

||

descriptorExtractor.empty()

||

descriptorMatcher.empty()

);

if(

!isCreated

)

cout

<<

"Can

not

create

feature

detector

or

descriptor

extractor

or

descriptor

matcher

of

given

types."

<<

endl

<<

">"

<<

endl;

return

isCreated;

}

bool

refineMatchesWithHomography(const

std::vector<cv::KeyPoint>&

queryKeypoints,

const

std::vector<cv::KeyPoint>&

trainKeypoints,

float

reprojectionThreshold,

std::vector<cv::DMatch>&

matches,

cv::Mat&

homography

)

{

const

int

minNumberMatchesAllowed

=

4;

if

(matches.size()

<

minNumberMatchesAllowed)

return

false;

//

Prepare

data

for

cv::findHomography

std::vector<cv::Point2f>

queryPoints(matches.size());

std::vector<cv::Point2f>

trainPoints(matches.size());

for

(size_t

i

=

0;

i

<

matches.size();

i++)

{

queryPoints[i]

=

queryKeypoints[matches[i].queryIdx].pt;

trainPoints[i]

=

trainKeypoints[matches[i].trainIdx].pt;

}

//

Find

homography

matrix

and

get

inliers

mask

std::vector<unsigned

char>

inliersMask(matches.size());

homography

=

cv::findHomography(queryPoints,

trainPoints,

CV_FM_RANSAC,

reprojectionThreshold,

inliersMask);

std::vector<cv::DMatch>

inliers;

for

(size_t

i=0;

i<inliersMask.size();

i++)

{

if

(inliersMask[i])

inliers.push_back(matches[i]);

}

matches.swap(inliers);

Mat

homoShow;

drawMatches(src,queryKeypoints,frameImg,trainKeypoints,matches,homoShow,Scalar::all(-1),CV_RGB(255,255,255),Mat(),2);

imshow("homoShow",homoShow);

return

matches.size()

>

minNumberMatchesAllowed;

}

bool

matchingDescriptor(const

vector<KeyPoint>&

queryKeyPoints,const

vector<KeyPoint>&

trainKeyPoints,

const

Mat&

queryDescriptors,const

Mat&

trainDescriptors,

Ptr<DescriptorMatcher>&

descriptorMatcher,

bool

enableRatioTest

=

true)

{

vector<vector<DMatch>>

m_knnMatches;

vector<DMatch>m_Matches;

if

(enableRatioTest)

{

cout<<"KNN

Matching"<<endl;

const

float

minRatio

=

1.f

/

1.5f;

descriptorMatcher->knnMatch(queryDescriptors,trainDescriptors,m_knnMatches,2);

for

(size_t

i=0;

i<m_knnMatches.size();

i++)

{

const

cv::DMatch&

bestMatch

=

m_knnMatches[i][0];

const

cv::DMatch&

betterMatch

=

m_knnMatches[i][1];

float

distanceRatio

=

bestMatch.distance

/

betterMatch.distance;

if

(distanceRatio

<

minRatio)

{

m_Matches.push_back(bestMatch);

}

}

}

else

{

cout<<"Cross-Check"<<endl;

Ptr<cv::DescriptorMatcher>

BFMatcher(new

cv::BFMatcher(cv::NORM_HAMMING,

true));

BFMatcher->match(queryDescriptors,trainDescriptors,

m_Matches

);

}

Mat

homo;

float

homographyReprojectionThreshold

=

1.0;

bool

homographyFound

=

refineMatchesWithHomography(

queryKeyPoints,trainKeyPoints,homographyReprojectionThreshold,m_Matches,homo);

if

(!homographyFound)

return

false;

else

{

if

(m_Matches.size()>10)

{

std::vector<Point2f>

obj_corners(4);

obj_corners[0]

=

cvPoint(0,0);

obj_corners[1]

=

cvPoint(

src.cols,

0

);

obj_corners[2]

=

cvPoint(

src.cols,

src.rows

);

obj_corners[3]

=

cvPoint(

0,

src.rows

);

std::vector<Point2f>

scene_ers(4);

perspectiveTransform(

obj_corners,

scene_corners,

homo);

line(frameImg,scene_corners[0],scene_corners[1],CV_RGB(255,0,0),2);

line(frameImg,scene_corners[1],scene_corners[2],CV_RGB(255,0,0),2);

line(frameImg,scene_corners[2],scene_corners[3],CV_RGB(255,0,0),2);

line(frameImg,scene_corners[3],scene_corners[0],CV_RGB(255,0,0),2);

return

true;

}

return

true;

}

}

int

main()

{

string

filename

=

"box.png";

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論