& x2 y9 z$ V( d5 L# c' D深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提取图像信息( G. I' N1 d+ A- G$ Z5 Y
图像标注主要用于创建数据集进行图片的标注。本篇博客将推荐一款非常实用的图片标注工具LabelImg,重点介绍其安装使用过程。如果想简单点,请直接下载打包版(下载地址见结尾),无需编译,直接打开即可! 9 O( N) Y5 e. y, l' X$ J% H) T; I) u9 e; V$ V( w% h; h
; L# }% J6 A4 W
感谢原作者对Github的贡献,博主发现软件已经更新,可以关注最新版本。这个工具是一个用 Python 和 Qt 编写的完整的图形界面。最有意思的是,它的标注信息可以直接转换成XML文件,这和PASCAL VOC和ImageNet使用的XML是一样的。" i5 H/ Z/ K9 [% z3 v
" L4 C4 D/ J; G7 a1 d( |
& g8 j& w9 ~' C& u F3 ^5 g附注。作者在5月份更新了代码,现在最新版本号是1.3.0,博主亲测,源码在Windows 10和Ubuntu 16.04上正常运行。& B u$ w3 o/ C/ ~
, F- W1 D/ @5 e0 b4 g e9 @1 U4 T% g/ ^2 ?
具体的安装查看Github教程:https://github.com/wkentaro/labelme/#installation5 ~, t, U, ^! ^) j+ ?
0 q% ?! ^. |4 x0 n% S3 D
' |# N8 h6 B( {( x
在原作者的github下载源码:https://github.com/tzutalin/labelImg * X$ X7 |& Z. h. v。解压名为labelImg-master的文件夹,进入当前目录的命令行窗口,输入如下语句依次打开软件。 Y- K* U. s( y' K7 B& r * r# k; L* R' j* }& ?- d1 h& N* w5 p6 Y& ]' Q) A- Q& D# n6 |) ~
python labelImg.py & l9 V; u* f1 I# @4 R p# e1% P$ H# y u! f; q6 |( w
$ q7 m8 o* }. j! W8 s8 q, A7 [
1 {2 H$ q' r9 U$ c* L# E) d
# V1 C, d: M+ c; d9 ^! B: A, K7 G; r1 u1 |
具体使用0 W! l! Z) Z( M! d& I
修改默认的XML文件保存位置,使用快捷键“Ctrl+R”,更改为自定义位置,这里的路径一定不能包含中文,否则不会保存。1 p$ L$ z- I1 z+ n1 g
1 C5 N/ S7 y; l
; Z7 h. u0 b; u1 [& X使用notepad++打开源文件夹中的data/predefined_classes.txt,修改默认分类,如person、car、motorcycle这三个分类。* [5 I l: e2 L/ K
" ?/ w$ e) ^. q- x9 n
& `1 q' ?2 N8 f. B0 A+ g
“打开目录”打开图片文件夹,选择第一张图片开始标注,用“创建矩形框”或“Ctrl+N”启动框,点击结束框,双击选择类别。完成一张图片点击“保存”保存后,XML文件已经保存到本地了。单击“下一张图片”转到下一张图片。0 f. `2 q, F# }' _% y6 U
3 r& |7 G. A% Z& F i& i1 i
1 ^/ e1 n4 ~8 z; \
贴标过程可以随时返回修改,保存的文件会覆盖上一个。 7 ]# q' K9 d4 _/ c* e , y7 [7 q5 _/ C1 a. V( V s" @: q7 U/ ^8 ]/ N O H, c完成注解后,打开XML文件,发现和PASCAL VOC格式一样。 & `! [8 ^' N" N6 e1 ~0 z4 z6 c* j i0 c/ F! e
9 A! \% ^4 p1 I
将xml文件提取图像信息 , {" O9 n# z6 F! r2 e下面列举如何将xml文件提取图像信息,图片保存到image文件夹,xml保存标注内容。图片和标注的文件名字一样的。 & p; H" i* S3 V# q9 R' Y1 R; y1 T) @9 o) V: |
# ~* A; ^4 }6 s8 |7 |3 j1 a
; l+ \. e( s( V% C# u 0 y6 B. ~4 u/ p5 t3 m下面是images图片中的一个。 # Z/ w5 V5 {0 R5 H 4 A% b+ V9 D8 l+ t3 a2 G2 `9 Z3 V: C. H! p- s4 W6 |+ s
下面是对应的xml文件。 8 ]7 Z9 X0 }0 M2 s" R4 f2 {1 N P! \( k6 N
+ Z3 V+ ?& ^' g
<annotation> 6 j7 \ P2 N( m; R4 \; A+ v1 ~2 P- u+ E <folder>train</folder> $ Y; Q& N. \. B8 x+ D o4 H# v <filename>apple_30.jpg</filename> 3 ^4 }9 I3 C: j( h- x <path>C:\tensorflow1\models\research\object_detection\images\train\apple_30.jpg</path> ' t, |' p) L$ b, Q* b <source>+ _7 C" @9 G/ N6 _7 ?) W7 d
<database>Unknown</database> h' L' _8 H7 n! c
</source> : ^" ]6 `, s% N2 C <size> 8 Y" F3 r& k/ c; ~ <width>800</width> + A) c! F" Q4 q <height>800</height>! m+ u( O I5 X6 A H1 m6 C9 b
<depth>3</depth>5 Y1 q* E, {$ `7 E
</size>" W, v+ |3 A0 P- u) T' w
<segmented>0</segmented> + X& [* ?; o. _ <object> ' m" ?$ Y! Z& I* F2 s; } <name>apple</name>- _/ J1 d' B$ G8 ~- m/ O Q
<pose>Unspecified</pose>7 J7 L& g Q1 X0 H* F( b5 J
<truncated>0</truncated>; y/ Z( _# Q+ G5 d
<difficult>0</difficult>8 x- O& \" Z& \( C6 u; p% Z
<bndbox> 1 W( M1 x, n; v& I <xmin>254</xmin> # V: C9 J* w" J9 Q$ n <ymin>163</ymin> - y* T" Q8 s! o% ^- Y <xmax>582</xmax> + i- l# h% y. D, o2 P <ymax>487</ymax> 5 G* A! R! I& D3 S7 @+ c' d </bndbox> * B& o1 T- N$ b) b r# @9 F+ T </object> V7 O/ ~0 y/ J* |- S! F& \' H& O <object> # X9 y! B- O' Z4 X/ C <name>apple</name> N$ m9 ~1 [) S! v: m) L" L <pose>Unspecified</pose> 7 l% R2 z W; D" V& ^# c7 q: Z- S. k <truncated>0</truncated>+ G1 s4 l) l' l0 O) \8 _
<difficult>0</difficult> & w C3 ]: z" q }2 p/ E+ f6 P4 o+ | <bndbox> : ]- v) ^- V+ {) D# ^. u; z <xmin>217</xmin> - u4 Q" L4 t' ?, I <ymin>448</ymin>' ~; b8 _* C- J4 H
<xmax>535</xmax>; p2 J/ K. i$ j9 ]
<ymax>713</ymax> & _6 }4 S, A5 P. c1 D' K </bndbox>& D. X) W3 t( k& M! o
</object> - n G* i- a: B, w* v4 U4 T: ^ <object>& `: s; i: H, ~( Q) `8 E4 {
<name>apple</name> A* c+ `. e/ r! ^) ?3 q. d
<pose>Unspecified</pose> & O9 L8 n6 h8 x! ^9 x <truncated>1</truncated> . ]' A$ u. o$ _4 V. h7 l <difficult>0</difficult> 3 X* |1 Y0 |6 Q6 x n+ l0 L <bndbox>8 D* g1 \: {" x/ F3 b
<xmin>603</xmin>% F2 w9 ^8 b0 [1 L+ K, J
<ymin>470</ymin>0 v& j6 v( W, D5 z; J5 e |- k
<xmax>800</xmax> : T! S6 S3 z/ v" u <ymax>716</ymax>( H" L: \/ ~- A5 Y4 b' v- |; s
</bndbox>: \. Z6 ]+ I; D" i! H0 Z( W( V
</object>9 k% g6 N8 l$ G
<object> & n5 ]7 Z y# w, S, H5 m <name>apple</name>" e# ^# F7 n/ P. b9 ]$ ]0 h
<pose>Unspecified</pose> % g: p3 } Z2 p3 [ <truncated>0</truncated>6 Z& @- d+ W* r! R5 Q0 x4 V2 ^
<difficult>0</difficult> - ^" ?+ u* n% K* n" D A( H <bndbox> 5 e* v+ y: L) V. ~ <xmin>468</xmin> ( U1 x- Y K" y0 X6 @" w3 Z <ymin>179</ymin>) h6 i V& }% B5 ~4 ]
<xmax>727</xmax>1 u8 S2 V/ Y) X% s9 W
<ymax>467</ymax> ) c k: Q% f. H4 Q0 B </bndbox> : L( A3 n& s% y) o- l </object>( b. r2 h9 a1 M2 ]! }
<object> " `7 O; r, v2 I: ?% a <name>apple</name>; F4 ?" J% ]6 r' ]5 u! C
<pose>Unspecified</pose>3 q& Q2 |- ]1 x( |8 ?5 z
<truncated>1</truncated>9 ]1 F% V4 j9 [# N
<difficult>0</difficult> # p" u. U$ U- S' w4 x, B! f' L% v! | <bndbox>' g" k3 m0 C5 I! i
<xmin>1</xmin>% t) o' m% I8 x7 {2 z
<ymin>63</ymin> $ }+ Q+ L; _5 p3 W8 d; z <xmax>308</xmax>8 k$ f) q' i$ v* @
<ymax>414</ymax>, R' ?! y9 ? z* h0 X: y) }
</bndbox> # ?# w5 Z- b( ]: d* I </object>6 G" V6 t1 i0 D% s
</annotation>) R9 Z( F$ n1 I* [
1 0 _( a- d1 x$ l" z2 ( H9 H e9 a, r& t1 ?# z. \- J3 t6 P7 {1 g O6 l7 D4 - ~+ y# t* o, X# ?7 k9 W! C5* G2 A4 Q! C8 N
6 % Q* v \# Z% F8 \: e8 J70 g$ ?/ V: b0 b& @
8 5 ^' N% H* }6 o1 B2 }5 n3 S, [9 : D* H% Y, `' K1 u" |103 ~5 s0 N% d1 ?/ j
11 1 _: Q2 h/ D4 G- x12% E4 X* W' R, N% s# K( u- I# |
136 |( m6 v# A+ k7 W
14 8 E) _9 P0 l: v15/ V. o* A9 Y& P
16. E Z' @1 x$ _" R
17% T6 ^# h4 b" \8 Y' w
18 ! ^$ @' ~& H, m0 P# M19 / h& y" F- \* o( X1 j20 : w7 U) e6 Y J3 v; e& Z( @21( q9 E& \/ d: {6 A/ D4 g
22 ! F( s% x7 i- ~, Q: k7 x23: Y. g. v' p$ u0 W+ C1 P6 P' ~
24 7 {5 G7 ?5 E$ k" i ^+ c25 8 I2 H+ y) M n$ g9 O9 U/ A i26. R Z& U# H1 d7 Y/ X
27 3 v2 j' p1 [; J% b' L: X28% w3 I; Y! D! Y; `# n. d; l
29 * l4 o# z ?( t. e5 X0 p3 l2 L30 0 }9 B8 r) {- v9 Z' ^8 h/ `4 N31 8 U+ ^% X& z5 K+ q; L# |0 r9 c32 # D8 ]) n4 L0 N: y33! U7 x% z) @4 p6 d
34 3 w% ^0 l' {- Q( a3 W35' Z, z# w7 t/ {! x# M7 E- ]; R
360 z; `1 G3 U, Q X, k
37- ~4 R0 u; }$ O# s$ P
38 1 n6 u$ Q1 ^$ I' @39 \6 P3 b, ]2 k1 `. V) E- q40# q) @7 q/ ^2 |4 l* F" X
41# u& x: x6 ? u7 d2 K
42- u' h( ~3 [. Y5 i
43 % ~. y/ o* x) X' u0 |/ B" r44/ h+ f R$ c0 U) T6 H& x0 l1 M
45 ( w0 d3 J. S/ g7 `, s46! ?8 b5 s2 U9 S F$ B! F# ~
47 % p' j& k& U' W48, x& a! {3 d) P" |# Y
49" a' ^1 ~" F1 _+ n/ T3 u* D: {
50! U# b6 z/ `: l$ c( ~2 A% R( R
512 R! \& N. S9 g* G9 a+ @# o( g
52 ! A' R# s" S0 }9 U0 ^9 X' e! k9 z53 ; ?/ a$ W" D8 [6 g$ [54 ! ?5 e3 l7 Y# m55) b% ^9 W r" S/ g2 n
56 ! ~) C' o9 y' {# r: q570 b1 m: D G' L! O
58 ; Q0 s1 M4 Q. f K: ]* f59! Q: r" G7 d; U( h
607 E6 j2 j; a1 Q: t
61% P! R( R& G( y* Q3 L6 ]
62 & |. S5 N7 g- `6 a2 n9 Y8 j1 p$ M1 |63( m2 {, g$ ]0 N
64* j$ K8 B6 S, |$ d; u( ^9 W% Y. ^ `
65! ?' f; U+ T; @
66 * V0 h& w5 e" u/ [, E67* }& x9 n; C. y1 k3 v4 s) M
68 ) v' {2 G( n* i6 x @5 N698 C. D( d1 }/ @
70 . x0 Q, g/ M+ P! H4 W710 g4 l. k' m9 `, b
72% S" i1 Q, R/ ^; Y8 U
73! |2 B8 g, u @" t6 Z5 L5 w
74 0 H, [ q9 r6 G3 ?- v, _将xml文件提取图像信息,主要使用xml和opencv,基于torch提取,代码比较凌乱。2 {2 F" k9 ^; b
; H2 R" `: p% P4 P- K# g4 ?
5 p/ I k% w( u' C% P3 Kimport os 0 @ f+ [! e z b! ?import numpy as np- ]# z2 [$ d7 h& u
import cv2 ! {; \8 K% t) Wimport torch! l( }2 j4 H3 y; {8 c8 C
import matplotlib.patches as patches ; y* O# m9 Z# F5 yimport albumentations as A 4 s( ~; g, G# ~/ d' zfrom albumentations.pytorch.transforms import ToTensorV28 H9 a) B8 G5 g# a! U) O
from matplotlib import pyplot as plt G+ G& M4 A" Z9 d: Zfrom torch.utils.data import Dataset 9 S- d# s, i$ H) z1 }1 {from xml.etree import ElementTree as et7 ~0 q2 k6 i4 ~; F: S, R3 ~
from torchvision import transforms as torchtrans0 s' V, J2 S' n, L
- g. S- `6 J: P' \0 a, O& b" D' C: r7 E# b$ t- `. A' m2 l+ Y
# defining the files directory and testing directory$ n# X4 \$ v- o4 r( F" n- [
train_image_dir = 'train/train/image'+ c8 ]+ k& u/ Q6 A; T% F
train_xml_dir = 'train/train/xml' : F# f' o- W8 C( V* `& D# test_image_dir = 'test/test/image'" D. I* V8 i$ ~7 j) H5 R6 A
# test_xml_dir = 'test/test/xml' + g: }3 F$ T2 ]% `1 j6 A% T5 c2 [/ q8 F/ q3 T: k7 K) }
/ M+ K6 }$ ^- `
class FruitImagesDataset(Dataset):, |) L* O' G W
0 M( P) G- c% j+ U7 t6 S; j. f9 c % f# C$ d! [# ^/ U6 [# l def __init__(self, image_dir, xml_dir, width, height, transforms=None):8 j" u6 k. R/ G* t$ W- a/ L0 a
self.transforms = transforms4 `9 _( a/ W1 c( ~+ w8 I9 w. p
self.image_dir = image_dir 1 \ h) G( K3 ~) j( c* a E+ \* K self.xml_dir = xml_dir 4 g' D2 a) C: I) P( N j. h self.height = height( Y- C! S. X0 Y) U) k
self.width = width $ m* _0 m4 d" V( p) U; ?. x' f( |* B* d! X3 ?8 J
: P) c4 G" X7 Z& W: D1 L% g0 N* }# B # sorting the images for consistency ! H" R2 Z1 Q4 G2 A # To get images, the extension of the filename is checked to be jpg4 q" k; }* ^$ a' r9 w# }
self.imgs = [image for image in os.listdir(self.image_dir)! M7 V' T0 D8 z
if image[-4:] == '.jpg'] ; h& A7 N0 @' c4 ]9 } self.xmls = [xml for xml in os.listdir(self.xml_dir)" _5 C2 h0 U: q& X1 u: z
if xml[-4:] == '.xml'] 8 d* I8 I9 r! b* L! C' N; |0 _8 o $ }7 i8 P) M& q' A. ]( R3 P) h, [- I- X. _
# classes: 0 index is reserved for background- F1 o4 {: l5 ^: M
self.classes = ['apple', 'banana', 'orange']5 [6 e6 p: ~- i& W
! d7 l+ h4 u" w0 p; d0 H2 P% ^
$ n; V6 q$ ]# G( u2 O; q6 g( q* y4 P def __getitem__(self, idx): / @; ~, W( j% ?. O- u4 _% j7 C9 n; s8 D: k9 t2 K4 |
+ p% v9 V3 w# Q) p
img_name = self.imgs[idx]1 s6 \# r2 I7 v- W% D
image_path = os.path.join(self.image_dir, img_name) ; V1 y: g* {, o0 W2 ]8 u 6 ^- e; ]5 I( A* D5 _2 \7 o$ D# b# v$ Q' `4 O$ W) F: i
# reading the images and converting them to correct size and color ) l- u; z* `, T# O img = cv2.imread(image_path) % O6 L" N/ q- _0 ~& P' U. l, v img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) . S8 Y7 [3 b) f: b" a img_res = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA) 2 c1 K9 B* r2 k& d' n # diving by 255 . U, n% c- I" h% l% J3 c/ } img_res /= 255.07 Z0 I( z6 c: Y2 K a
$ d7 j0 V: R' k3 W: l & F2 T: ~2 G+ P. ~: o # annotation file( D' @$ y3 ~1 k
annot_filename = img_name[:-4] + '.xml') ?/ z" F8 M" G3 ^0 h
annot_file_path = os.path.join(self.xml_dir, annot_filename)( l: a# M, _4 h2 L8 e
6 p/ x. y: l0 D0 m
2 X- J! s2 i6 x- F+ u" Y9 a( E2 ` boxes = [] 9 d& H6 V' o1 V labels = [] @: z3 G) `; S tree = et.parse(annot_file_path): ^. ?' L! n: k* h. j9 O5 b
root = tree.getroot()5 h$ I- J9 s; N% s4 v
1 i( q7 q2 C" i# s6 G
7 x( H5 Y! g/ {* J9 z # cv2 image gives size as height x width ! N" Z7 u# L% R2 Y3 a wt = img.shape[1]/ d2 N$ _5 u6 [, G7 ^
ht = img.shape[0] 3 c; a% p$ T$ L: \7 B2 z) B3 m/ n3 o6 T! H
3 {0 h+ l- D$ c4 u6 I
# box coordinates for xml files are extracted and corrected for image size given) S! F4 b/ m! `2 g' K
for member in root.findall('object'): . t. \. p3 M3 x v3 `$ p0 m' x labels.append(self.classes.index(member.find('name').text)) 9 n1 p; R! W4 [8 i" D$ n; B) m2 g/ Q3 _" z, w
$ ^" J# t6 c! b7 J! e # bounding box ) ^- e! H, h( G3 e xmin = int(member.find('bndbox').find('xmin').text) n! d5 W4 e" V \ xmax = int(member.find('bndbox').find('xmax').text) 5 ~; c3 S i9 S) ]7 h4 ~ 0 ^( R5 h2 G7 b4 X + ^% \# l8 n; A5 a# ~% ?- @( p9 j ymin = int(member.find('bndbox').find('ymin').text)3 q; ]- @9 F: h/ }9 p% o7 L* n
ymax = int(member.find('bndbox').find('ymax').text) " J7 k" j* e& u% g6 z1 Z+ U7 H. |" ]; B4 D# B2 {
( `/ T# u' A3 g( w
xmin_corr = (xmin / wt) * self.width # \/ q) r4 l& E) {3 E- W7 V xmax_corr = (xmax / wt) * self.width / O& \# m3 N/ Y& |9 F ymin_corr = (ymin / ht) * self.height. n1 ?( {7 K8 ~+ N8 B
ymax_corr = (ymax / ht) * self.height2 `4 M6 k) k# D0 C5 a
boxes.append([xmin_corr, ymin_corr, xmax_corr, ymax_corr]) * k4 X) }. p" b+ x0 P, m) o2 n4 p/ q) e9 K7 `: T2 A
: m8 d$ n j( j3 `! [2 F
# convert boxes into a torch.Tensor$ _% v- `6 j G5 O- _! O
boxes = torch.as_tensor(boxes, dtype=torch.float32) O2 q' W ~" n+ p0 z. Q! V, z! E, @2 @
4 f! Z3 m! g; i, F& ^$ y5 ]% j # getting the areas of the boxes 0 t4 a9 W( @4 B' S: t area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]) 3 w- F* i% w! v) ~0 G+ Q! G4 X8 R8 r* K8 W6 N" n4 ?+ m. _+ A
0 m W# `- s: d* G7 B" C8 v$ V J
# suppose all instances are not crowd " n* e8 c R0 v3 `3 k* b iscrowd = torch.zeros((boxes.shape[0],), dtype=torch.int64) * I; [4 ` h" l( Q9 o J c- p9 H' E# N4 ~
8 X$ ?: Q- v3 N labels = torch.as_tensor(labels, dtype=torch.int64) 0 M, P0 j9 ]9 C- Q& B1 q ' P9 l4 _% G; q/ l" I ) ~0 C! \) `7 Q# E6 P+ [ target = {} % s" Q V" s$ d target["boxes"] = boxes 3 d( u- w+ z$ ^. J6 M2 v6 `; e target["labels"] = labels+ {+ ~4 z$ ~4 f% Y7 n1 h( l
target["area"] = area K, D3 g2 o# G! `; I* z0 O/ u- Q
target["iscrowd"] = iscrowd ; f: i# D# W% O5 V' x # image_id% S1 S( T. \! ~5 a, O- I
image_id = torch.tensor([idx]) # L- B* M$ M K! u, h& e; r, c target["image_id"] = image_id$ D- K0 w( k0 T: J' @
$ r' m3 I; e4 ~$ a4 Q! |
' t4 q7 L9 Y, V! p, }5 } if self.transforms: 9 \' K% ]0 e% t! |; G sample = self.transforms(image=img_res, 1 C" W6 x& k# F" q! d6 v# ` bboxes=target['boxes'], ) D. o p( y2 I8 s/ g labels=labels) ( C/ ?6 F/ k, a1 k- r/ Z) }3 |% W, E! r, G
1 m5 n+ i, t1 h7 T
img_res = sample['image']/ X: h$ Z: Y! a' h2 a
target['boxes'] = torch.Tensor(sample['bboxes'])- f2 x' F) V4 a% b6 d+ \& r
7 I; J: C! y7 h" g9 b$ v 4 v) R5 \" g7 w: x9 w# function to convert a torchtensor back to PIL image/ ^2 _( H* `. F* `; p1 G* q
def torch_to_pil(img):5 U' B' r2 O1 T7 k' e. B
return torchtrans.ToPILImage()(img).convert('RGB')3 L: a, _. A- x/ O% h
) G. x' I! }! R7 _" Z* V: f " b* ]8 b" D4 \& _% |" o. ^, ^6 D$ F- D7 l: _% {
+ _- y/ N9 A/ J6 s- k% @8 qdef plot_img_bbox(img, target):' z) o. G9 {# d
# plot the image and bboxes$ h3 t1 _8 O ~; }4 C- q
fig, a = plt.subplots(1, 1) 9 h8 z `( S' t. d' K8 W fig.set_size_inches(5, 5) 4 i% h1 |6 q4 l6 ~% a! u" P& _! X a.imshow(img)5 f/ i) M. X. T4 _1 N8 p% L
for box in (target['boxes']): - S, {5 [' ?1 t L x, y, width, height = box[0], box[1], box[2] - box[0], box[3] - box[1]! ` v1 z, @( n; i- i5 O2 Z2 i
rect = patches.Rectangle((x, y),6 \: r6 Y3 `) B
width, height, . p# V* t. ]! b8 [5 s) z4 m O linewidth=2,4 q" L' T, C* n& B$ j
edgecolor='r',3 B5 Y' v& u0 V
facecolor='none') A7 C7 \9 m" {" E. O9 @
2 i' s, x- h5 U, w 7 c8 Q* \) m. A$ H) B0 J # Draw the bounding box on top of the image ' E+ ]0 E. E# r8 [( l( q* n% f a.add_patch(rect)5 Y+ O1 S9 c* i
plt.show()! u* g9 p6 Q" F" }! l
/ C+ g; ^- h Y: Q( n1 @: P 2 S$ T7 s6 g$ @, U' g3 v h {* D$ g' Q2 w! n. w3 A+ v0 w
* U/ `1 ? h7 O- S3 Q4 hdef get_transform(train): 7 Q' X& P2 Q9 j. l- M4 H' T if train: * h1 C. C! j0 R return A.Compose([ 4 U0 `" D% e! P. Z* ~, Q# _2 M# V A.HorizontalFlip(0.5), 7 \; i9 m7 `8 w! X% C. ] # ToTensorV2 converts image to pytorch tensor without div by 255 , m: J- d8 f* v2 |" ^ ToTensorV2(p=1.0)" ]: ~7 u6 y% ?
], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})" k4 c/ Q- ~$ K0 n
else: & F! V) M" ]0 m# k8 b return A.Compose([ # s0 ~" u6 e) v% ~! w ToTensorV2(p=1.0) 5 Z* w" D( n& X) Q' v3 \1 ]+ { ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']}) 7 R( S4 Y# H9 x 1 b, N# n2 ]4 f8 w4 }9 ? + \- A- x7 k& V- G# h * K5 E1 h8 V, L3 O) e% |2 x& e( t+ ]1 L
" [0 S- o( ~* ?& ?1 S5 Z! t: {4 Z2 r- r' b s# r
dataset = FruitImagesDataset(train_image_dir,train_xml_dir, 480, 480, transforms= get_transform(train=True))1 a' g3 v& ^6 z5 S% q& N5 b" t: \4 k
& ?0 Z- A5 i3 s, ^7 Z0 F4 |, k, J/ o8 R& O' I6 @
print(len(dataset)) 9 [, R2 I1 x/ N6 Y, S" I* }# getting the image and target for a test index. Feel free to change the index. ! V2 h2 d+ l5 }0 F+ R1 \, aimg, target = dataset[29] * [' R! D0 T [* F+ [8 Y9 ]print(img.shape, '\n', target)9 T8 @, L. L4 w
plot_img_bbox(torch_to_pil(img), target) 1 a" d4 n+ m( T3 a6 Q0 L1. Q7 d0 Q% i; Z' I. X0 S! j
22 r: {! N" |# H+ @! V
31 Q, @8 t; d, A* w
4 4 Y1 U$ j( X y0 ^, m5 H4 I5* K/ A/ f# C5 O
6 6 n, }6 W! `1 {! M' v7- J6 Y% T! Y3 Z3 C. E
8" ]# F2 Y, n* G; \- K
96 Q" C) C/ l# [$ j$ S
10 j0 e2 Q9 @9 G0 s7 g11$ N% g: L: t, b5 p1 j( R' |
12 - B' r9 d1 T6 Q: Y- d$ U/ A( g13/ ~6 b( `; z% g* X* x( ^* `: a# |- G) F* ~
14 ) f4 |, f1 o B$ k# ^15 " {! Y- O: c" Z4 A16% S" n4 f$ y: y. D, T
17 * \, r! F! U3 R) {18& |! n4 n8 k; N: b9 J
199 I1 e# G" b$ y. `) E: T$ W
20 ( q+ P3 e; T% D7 q9 S21. V. Z( a0 ]( S
22 " A4 U" y( X* ^6 I, [& v23( p& a P+ g4 y
24 u' D+ E2 S" J3 a
25% u. U! i; `! z. d: d8 ~. ?
26 2 y2 G: X8 ~" b- Z27 5 g, ~2 d' Y0 l, |6 [28 8 V0 z6 c# O' y8 k, M" `: N29 ' t- b! O9 u+ m30% h2 |0 G ], S- ?+ U
31 , R0 \5 ?* ]7 s8 {' ?) B32 5 T) a% L7 q6 ]) Z' k+ w33 6 C. W# }& i( K6 ^1 X34( j. z1 j3 W8 i# s: d2 A b
35/ q* T9 E% d+ F6 R& I3 w, R
360 I) T, H, |8 |1 p- Z
37/ m! o3 y7 I% g4 |$ m
386 h6 ]" F6 W1 T M5 Y& D
39 5 Q& B/ f; v, U! D/ @6 e2 r* v40 ! G+ T) l# d) d41# v& a- U% |5 ]( S& w
428 w9 y: H. Y" P/ H) U
43 0 n L( B( k# ^% f4 G5 U44 N: D) K, h$ e0 o) l454 J3 `9 G' e, s: d3 h4 o' [! _$ U
46 0 Y. s. j! n1 A+ h: M' j. a) D4 r47 / q R2 }3 Q, t9 `. N+ A Z# q48. x4 V; M, ^# o
49( Y9 l8 s& F m6 I, G
50 * H' i1 o* A% g51 , \: A6 Y+ B* j% v. J521 v& Q* Z% ]; M7 k5 v
53 5 ^9 k7 [1 O+ b/ T& n5 i543 h7 C# C# e' N8 |9 y9 Z' @9 L
558 ~. q2 S+ i% t$ e7 c
569 M& g/ ?1 q; w( g3 d
57- q% ^. b. C2 Z1 U6 ]' z$ }7 t6 [
58 . v4 u0 Y: j" Y% D, n# I' Q# t; k59 8 U, w- \4 U+ v) Z+ ?60 ( a+ i7 l1 l- {6 X0 W) k3 ]* i3 B61 4 q) q- o% g) z6 k7 `& J( J: T62 , d' Y9 R0 u3 F) a5 H' W638 M6 A( r) g) Y1 v" Y- }
645 w5 w" L/ Y1 V& I$ @2 c
65/ B: n/ {6 w3 e# f3 L
66 2 ?; H& d* ^2 V8 c" ^9 O2 M8 A67 6 @; e' O8 q/ v, t68# k# e6 i {0 f( E0 x/ ?! C% k
69 9 L4 u2 x, ~- k/ I6 B: J% Y2 y2 K7 d70 # {4 ^2 w( V9 Y& v71 ) L/ A5 D" M/ L& |6 N: s72 # X0 J" a9 @7 e c5 x9 K! w739 A9 G# E( t1 n' n$ @% v/ A
74 2 E# w' y+ _8 Q( [75 ' G2 n7 |3 X0 g6 ~/ _. y1 ]76; e# v- [& I$ k# n+ e
77 3 J5 \, `! Y1 E" h. s781 u! j% d, h0 P8 @- w) W& O
792 L$ U1 k% {* Z% r5 {1 h8 X. H1 T
80 2 \0 n. O0 E, P" |: L( X. G81 ' Y5 _! _ T- h$ i# @822 G- @7 k$ t/ e. }0 p
83 % v) M0 X) f: P8 }1 m9 C84 ) C+ |: U0 }/ p- f4 \9 z1 Y85, |- l3 T0 k7 N: ?
86 D9 S- @8 N$ A. k5 i+ t# h, t9 U
87, @) R c5 t1 [( H
88 " F- j2 ]8 C5 I: y& d& D- a891 a' [" [8 I2 d
90 , X/ b* M6 Y3 {6 W+ z7 w91 % T9 M7 F) O; v0 M/ |8 V+ S- D( m92 ' p& a3 ?) t) s' r% Y93 2 \ h. d b9 p$ w' f! I8 b940 o7 P' S7 Y7 @, \$ {/ D* f
95 / J1 L A, R& ^% U4 A960 }, x5 Y) @- i' K+ v
97 5 t# L) T* _% C0 \6 t4 s980 P! M% Q I7 L, s7 D8 Y1 U& B
99: T4 f5 \5 f* J& d+ h4 E
100 ( M. z9 x* x% K/ Y4 e" I' Z1014 f; D( g! d$ A
102$ x) C* T3 w+ J, Q; G
103 ( L' x; a! o" V2 l9 T104, ?/ a0 c' N6 L% |. B4 J( r2 l5 f
105 1 ~; @8 l& S. L6 R, a: E106# @1 z( R- v- k1 i2 _9 M$ ]
107) ]7 M! j3 z) P, N( i$ r8 k, G
108% d: q" x4 g& @' J+ i) u; N
109) \ q4 Q! Y% {0 C3 `
110$ X; R) Y% q- J# e+ C n9 x
111 $ }' d( L r1 h: V' v! ~( P% i% w7 E112 $ X% Z6 z z1 [& o K w; I' @113 ( H$ {* x# P( W K* x114 ! G) E! k! D2 l! K. h B, |115. w- F5 E$ \! v) K8 g6 y
116 9 |( ^4 q1 @: S117& t! J; m' i1 ^; J
118 % I, ^2 ~) L1 G119- s. b6 s& f9 H7 M) J# q
120' T3 b, H; W, N, _6 F2 j! w
121 / O+ @9 {1 k* Q6 O122 ) f9 \9 n' v% v% P. |1233 Z+ [& V Y8 m/ D, F2 Y
124 - P0 G2 v1 _* z, \( o125 " s1 S* D& O* I5 `126: h! |) P+ |. j* i
127 ; a# ?9 a; a+ `( @128 . l. C2 t7 Q2 T% U1 e4 T0 t7 u3 c129 & j9 I1 T: _1 x3 O3 Z- S0 x130 & V( @# j- p0 a, r6 u( Z131 7 [ G" L+ L5 B' r4 `0 O, K' @132 6 X2 w- f# y+ h! p, K9 L133* F' {: U5 S, r: f+ r7 t! f# C; b! L
134' q5 Z5 q9 H' A2 j$ U# u+ ^
135 ) H/ `0 W; [3 V( i) _136) r8 G* z, V" e8 U
137 1 e8 B, C( n' v3 x138, Q2 v) [0 A; l
1394 h% }6 R5 V+ ~2 i) C
140 0 h* z; [3 ^( ]# i) n141 u* E% A$ f; Y" {% F1 N0 j1 ]
142 8 g, K$ y% y3 D/ r. ?! O143/ J" I# q2 B& U4 V9 F7 r
144 ; O, t* D, m- G- I0 B$ A6 }145& q) A8 ?. j m; g+ b0 J; k
146# v4 Z& H6 W. M9 r
147/ f( I" |9 Y; _( d& q% B; G
148 ' G$ T/ G" ]( O) S& W) z1499 h9 H7 C+ O4 Y( n5 Q) D7 G6 Q. `
150 6 H8 }4 ^# p4 _( m) ^151+ P- {* _- g+ f$ a& X/ t* e
152$ V b0 ^2 C$ V$ T
153+ o( {' _$ j0 e/ ~# Z- Z7 `
154: E1 t- C% z/ }6 }/ i
1551 N& Y+ o, a$ x" T) C$ l0 {0 v1 a o
156. a* H* s$ G- J/ q! [
输出如下:: B! X k) N; u- H
9 M. k3 Q2 P( G! o