' ^6 Z0 o* i2 E" r. Y- ^- I将xml文件提取图像信息2 {) X4 J4 f6 l1 d! b3 F( {
下面列举如何将xml文件提取图像信息,图片保存到image文件夹,xml保存标注内容。图片和标注的文件名字一样的。 * t: w, X# [9 f8 B/ Z8 P& T 6 o/ M6 k2 d: t% o5 y( T; x# b% H1 m9 [! U
/ Q `% E) ~! A |+ o0 |& ^
3 K/ i4 ^7 v( N
下面是images图片中的一个。; s! i" ?: U d3 n5 v
' Q- d/ e' s0 k' t4 T
" n! L, C* l5 O& }' g! F
下面是对应的xml文件。8 T1 I8 p7 O) Q/ s! j( d
9 U& o! E4 ~3 n. T
! w q+ y# ? @* ^( D- o# z
<annotation>' {9 [$ o0 c0 `2 R4 E% H
<folder>train</folder>5 Y& }& H/ K4 M/ O8 ?
<filename>apple_30.jpg</filename>2 J' p; x( j: C$ ?& f1 [
<path>C:\tensorflow1\models\research\object_detection\images\train\apple_30.jpg</path>" d/ `; F" f% y# [* [
<source>! D5 ]" {2 s0 F: M
<database>Unknown</database> , q$ D! `" W) b2 d: n </source> % S' J" s+ X/ i/ r. T <size>, I7 Y+ V, u, o6 ^& q
<width>800</width>0 l4 t( l. |- S$ S! a( p
<height>800</height> ; \" ]' v7 v- T, r$ N6 J <depth>3</depth> * J/ X$ Z& c2 F. |' u </size> 0 ^$ |+ L1 P( j" g2 x: Y$ b3 n <segmented>0</segmented>: @9 v9 B/ m9 U' H6 E
<object>( s* ~2 d0 ?* @' S/ z1 ^" h
<name>apple</name>- g; {! k1 `% x ]' ?) W1 r
<pose>Unspecified</pose>' R/ n- w4 S5 L% g7 p) i/ `7 x' @" W% k
<truncated>0</truncated>: ]: X* ~9 Z3 `, L2 C
<difficult>0</difficult> 1 W7 x! E4 ]* j <bndbox> # d G t: U3 E, b' v2 U <xmin>254</xmin>( f' G- F. ` r# ~# x
<ymin>163</ymin> 4 L7 g4 u- N& u1 j' l <xmax>582</xmax> 7 A; o' I. F/ z. |; O _2 h, G <ymax>487</ymax>* o2 m- |" `' ]% ]2 h0 \: ]
</bndbox> % \" J! U2 x: A) l' T </object>. n& T4 N" J& Z) L3 C
<object> % o4 y0 h+ m! [. |" ~5 r1 y2 h <name>apple</name> 0 |* V0 N7 h- c8 I0 W( }% Q$ D7 A <pose>Unspecified</pose> # m9 F& W6 u6 `3 ?, U <truncated>0</truncated> 0 } f j$ B7 C c: Z7 ~' d: ] <difficult>0</difficult> , U3 Y, r7 c. d7 o! I6 c5 {$ w: H <bndbox>4 c9 v! Z+ w# K5 Z6 g! f4 c# j
<xmin>217</xmin>) Y( v" b3 b' }) W' |, l2 C9 A
<ymin>448</ymin> H/ w6 |2 i% d <xmax>535</xmax> 4 G" U, c( j: y1 S3 Y) k- Y <ymax>713</ymax> ) e4 Y3 }9 z/ r' G7 O1 i </bndbox>" a2 \: i$ g, U- ~8 @
</object> h) {" {4 {1 k B& o; Y
<object> 7 ]; G4 {5 B: C* e. J- {! |3 m <name>apple</name> - L/ [6 K# X2 m+ L! o2 g; |9 O2 { <pose>Unspecified</pose>$ w1 S% h9 p0 i J/ d# t; K
<truncated>1</truncated> 3 _( _4 U% r/ H <difficult>0</difficult>) z3 f" M' X: D6 i; B6 G
<bndbox> 5 s' g7 O5 _8 z. d; X W( `3 n <xmin>603</xmin> 9 m, C3 |; U& Q2 y O <ymin>470</ymin> & m$ k8 G" N+ V$ ] <xmax>800</xmax>& u( V5 ^% J$ p% q2 L( ^. i
<ymax>716</ymax> p7 \. Y$ v5 g3 L* J+ } </bndbox>. p5 [8 f/ {* M9 _
</object> 1 ~7 r. h8 z, U& J% {$ \0 z, l5 m <object> % ~0 @, ^4 X5 G* Y- Z& L$ ]* l: R8 @ <name>apple</name>: P- z1 J) @( A$ L6 A
<pose>Unspecified</pose>2 g; `7 m: r9 ^
<truncated>0</truncated> # S) ]7 ~8 |2 h4 Q" f <difficult>0</difficult>8 b1 q+ @: W# L; y9 F
<bndbox>: s) m6 e# d# v% Z% C0 F2 Q+ b. b+ J4 I
<xmin>468</xmin>! p8 U7 M ~6 y! U/ J8 T" ] y$ L
<ymin>179</ymin> 8 F- v6 i* ?: f6 L' Y9 }0 o <xmax>727</xmax> - N9 y8 q9 V: t$ m( l0 b9 w, v <ymax>467</ymax>8 X0 B9 i& Q5 P4 d" ^
</bndbox>3 N! } a6 Q- M
</object>2 g/ f4 i( H% n i/ M( d
<object>' k1 a3 R8 g/ u* j# Y! d7 n: E
<name>apple</name> + Y# u1 K0 h# k1 U0 J+ i5 V <pose>Unspecified</pose> 0 C1 l# ~ q' g) \& w5 f- F* U) } <truncated>1</truncated> / U) U- \; H, o* K! ]7 { <difficult>0</difficult>5 m3 K4 _! j) Z5 |5 E9 n
<bndbox>6 X- `) I: c" y$ Q) ^# S1 p
<xmin>1</xmin>- {& z( L0 @8 v6 x: w
<ymin>63</ymin>4 f2 c1 q- A$ Y4 @% m; \
<xmax>308</xmax> + y# |& \+ o$ b$ z <ymax>414</ymax>- V5 [: g/ d" Y' d% r
</bndbox> / e7 H3 j& T1 g4 [; a </object>7 h; ^" ~8 {/ V: O. E) I3 o
</annotation>: r0 J! L- Z7 F" z( x
1; ^4 H- ]5 F. I, w
2 : B5 [) U) O4 h( `/ u, R% J- z1 s% m3 - V3 m% }0 |+ ~4 [9 r9 ~* @+ h4 + U5 w0 M* J- L( q+ a5. W6 I6 ?" A4 x& [
6: M; `9 y" I# `$ u! _2 G& N! A
7 9 [8 r& M( G2 @( M& j8 % w# G& V# c, L' _7 F/ ~# @* [9* G% R; ]# K. g$ L. }
10 % R2 o- v% Y) b" A' A117 r% i5 G9 {, {( h6 }
12 ' I! y @ y; u6 ]+ I- e8 r& q13; j6 y7 `/ e1 i, R& I5 N. G
140 Z" {3 W" ^- t; ^5 K: Z. S
15 , P T. ?5 `) o* d162 X- R9 g3 F. P# g% K
172 t0 t3 L. S+ @- s# i/ v
18" {9 ?, }; C; U7 Q; B
19+ l8 u' e5 O4 d8 O" z% m$ y
20( Q( v( @ i2 S- S2 c
21 7 P9 Q0 Y- L# \7 k' {$ f22 8 E" d+ x1 Y0 u* Q23 ; r6 @' a- q# x% P, M) F. M7 `, C24' \) k6 f. _6 [3 A- f
25 & A; o; l5 z: r2 Y0 H1 k/ a26 $ J) d, V4 ~! t" k1 Y! J27. Z, R3 h/ U2 s
288 l: J9 e* ^, J) Z' ]- v" @
29) N# v8 s" G& \6 a$ j$ L$ V
30 # p6 K! G, t0 j- F2 E! Q312 Q$ j2 z5 n. |
32# x1 J, M; S% c
33 9 G- R' R: @) A( _5 q# g34! X7 r8 c( p! a0 o0 o: q, Y0 E
35 . k& X; J6 Y! B; X36: K2 z8 D [; f- m; E6 Q; f3 U
37 & Y. Q5 t% Y& M5 Z( }388 F: @0 H; J3 V, E
39. s# X+ Z0 s R* |
40 5 G2 [/ @5 e& A* I41$ U1 g/ t8 x$ L% p- K
42& r" l* @5 |2 g8 c0 e% H, B
432 h, T# m' Q3 q8 C+ b/ q
44; [/ H' p3 r* g
457 \# H+ x9 x0 A0 Q
463 n% Q1 z( s9 N8 W
472 V) o4 ]6 D# W: T1 n2 j! I% \7 D0 P
48! m4 P2 g# f8 q$ s; Z9 T! H
49 : A7 W% Q* W9 L1 _* i50& o) \8 b/ @( ?5 ~4 O) k
51, _5 R3 W$ Y3 x& `; }# {8 `
52: O( c$ I- k' N2 E. [
53 8 b# L5 l* _4 l- s7 P- H541 a; z% X8 Z; k6 ^+ ^, B- H7 N# t
55 2 e7 f6 u y# G+ Y. q. Q& o56 2 J3 K& ?2 l; ?6 C" P. n' i57 : c/ q K d4 M) {6 l' l58 3 v% B8 Q" L: Q7 x59. t: t) P4 S1 Q$ B9 [0 ?
60, R/ F( v: Z$ R! k. J! U
61! Z4 H7 U, e/ g5 Z
62 , N' G- Q+ ]- @4 o; O63( ]& [" w1 C# w' V$ P# z T6 n
64 5 L5 j: o0 V* V# R% ~' T ^; P65 , s( a6 u5 w. y: L2 [$ `66, b l" \# W) m' Q7 ~- v/ R: G
67( N+ t' }% y, f, S' h8 F \
68' K# `% A& b* j8 ?
69( I6 _; y( S) A3 e; f6 n( M: @
707 J5 x- Q6 p7 x5 x
711 H6 ^. S- n8 F1 M6 H# y
72 - X8 s$ h/ o! Y" t' }" _, ?) R73$ S! _+ r! O- R! R
748 q! O5 ], `' _8 e
将xml文件提取图像信息,主要使用xml和opencv,基于torch提取,代码比较凌乱。$ O& _! a0 B- l' J G
" }7 D0 ], y; ?
$ h1 z: {$ z3 |/ D( Mimport os V, k7 B) P& |5 z6 }
import numpy as np 9 N0 E* q' V+ T4 ?/ L/ ^import cv2 8 p7 S+ Y/ ~5 U; y+ L. Oimport torch! w# G, l! }0 k' V" n2 d: B
import matplotlib.patches as patches: m6 O7 A9 c) G* o# K0 \8 U4 o, p0 K
import albumentations as A , D7 U. C( ^1 X ^( T6 h( [5 Jfrom albumentations.pytorch.transforms import ToTensorV2 " e2 J# D% Q8 R. p# H. i, u2 bfrom matplotlib import pyplot as plt 2 Z1 ]4 {8 ~4 ~# x; Yfrom torch.utils.data import Dataset ! D( u7 m% ^6 Y7 l4 Ifrom xml.etree import ElementTree as et : e( K+ y" B a( H" Gfrom torchvision import transforms as torchtrans 2 X, B! V- w3 |8 R 7 }6 ^7 Z% ?' Z1 T% s ' A# k5 W# t- T9 ]+ V& H- j& `' r# defining the files directory and testing directory1 I& J, Q3 k9 {: C
train_image_dir = 'train/train/image') w# U4 T# X# p) O" x- h( y
train_xml_dir = 'train/train/xml'' k; i! e3 L$ g& x b; e, d% E
# test_image_dir = 'test/test/image'3 I i) P4 I. J+ Y% y0 f
# test_xml_dir = 'test/test/xml' 9 N8 `' N2 i' D$ D 9 x) J G' K9 h: k' e / z6 s) S( R) y9 q( V6 x; ^: Hclass FruitImagesDataset(Dataset):' S7 G0 ?8 s8 N# C7 E H
5 s6 ^1 f* {- O/ u* \) G
4 ^/ \( N7 k; D4 ~
def __init__(self, image_dir, xml_dir, width, height, transforms=None): K; F; M: O7 H0 l& B8 H2 ~2 |
self.transforms = transforms4 e; D5 P9 U( w9 `$ g+ _$ Y' c
self.image_dir = image_dir3 F( D' o2 P: p+ D* n
self.xml_dir = xml_dir; ?# {6 v8 A4 t" W- m& h9 z
self.height = height# s8 q/ Q. [3 [1 W- L$ ^1 t8 V3 _4 o
self.width = width) Q5 |, I. r* D( t; g1 q4 R, B
2 e1 |, o$ m9 L1 Z- U y4 j
; y% I2 w' B a0 n # sorting the images for consistency 9 F6 u$ ^4 l8 Q+ [' X' {9 } # To get images, the extension of the filename is checked to be jpg: B P* B; w p' B
self.imgs = [image for image in os.listdir(self.image_dir), s" U" r- V2 Z. k
if image[-4:] == '.jpg']5 F, `1 E* E0 m* `+ Y
self.xmls = [xml for xml in os.listdir(self.xml_dir)0 B( {- U) t/ X, y N, J z y: n
if xml[-4:] == '.xml']8 z9 u& K5 p* T2 m1 u
5 ?7 i+ U3 B! H: v
) e5 {) F X7 L # classes: 0 index is reserved for background3 y9 x/ V& Z% n, a ?( Q1 q
self.classes = ['apple', 'banana', 'orange'] 3 W, }5 Y# s, M2 _ : l$ r* b5 c7 R9 G1 e% X6 R0 p) x( @+ Y& @9 p
def __getitem__(self, idx): ' c5 E( s# W% z& O/ N2 l* v. [0 H
/ j6 N' r& b$ h' N img_name = self.imgs[idx] 4 w* n! \4 [( V& R: ^ image_path = os.path.join(self.image_dir, img_name) ( p" r5 ^% `+ P9 |, R - I2 I( }; F" g9 \ * f3 l+ S! D2 p, v% Y # reading the images and converting them to correct size and color ! w" E) ^1 V0 B$ W img = cv2.imread(image_path) $ b E* e5 c. T; \7 R% s! e s img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) l8 L8 Z8 r" W6 X( Z3 i4 } img_res = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA) * K" h% P2 r% } # diving by 255 3 U6 f# V% x& I% ^( ? img_res /= 255.0/ y# p9 v( w% g" F+ ` Z
/ T# Z$ ^; M, R+ b1 [- b
( H# N* Q: _! ~, C # annotation file1 h! l3 ~( a. c3 E% E) g
annot_filename = img_name[:-4] + '.xml' + N- F4 ~/ ]* y9 V+ a- {" \0 f: E. X annot_file_path = os.path.join(self.xml_dir, annot_filename) ' Z! p* L, L. p7 D% X# T2 u( @1 N3 r x+ J( A
- ^' g& n' _% @ boxes = []5 o7 _% H- I. t9 j
labels = [] # `1 j$ g$ ]6 f) M$ T& O" ` tree = et.parse(annot_file_path) , K; a3 E! G" r! o4 r3 T root = tree.getroot()) k% E1 J! N) m8 s' H$ w
9 Z7 H9 w5 D3 y: v5 x- G2 l % A) \) ^: o' N& _ # cv2 image gives size as height x width 2 T5 B; P1 |( d: ^! ~' X wt = img.shape[1] : T% X; F: }4 j! q5 O$ Z ht = img.shape[0], c; H- X, q+ { z. C4 k
! J" t- [% D s$ H2 J) Q( U4 _. l; _" h7 j: t: I. T! E0 h) h
# box coordinates for xml files are extracted and corrected for image size given 3 J+ ]0 A" u4 m a for member in root.findall('object'):7 b1 u; \7 F. T
labels.append(self.classes.index(member.find('name').text))! o4 H6 o# J' |# w
5 N# y2 y/ o8 C# }* {" e$ e & I4 ~! ?0 b6 p # convert boxes into a torch.Tensor6 A6 b4 S& D n3 B; ^- t3 N
boxes = torch.as_tensor(boxes, dtype=torch.float32) . ?% g1 Z2 _: [8 q- E; Q& C; j+ `4 E$ ~& c G! a |& }
, g2 h2 C" V2 H' y( n # getting the areas of the boxes ; X4 Z6 T( C; U9 ~' a. T( A area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]). _6 c. T2 v7 T: \
+ b. q6 x! U8 I+ R+ n
2 G+ T+ F ]+ e* T' @' N7 E; f E # suppose all instances are not crowd 8 K' T" i6 Y4 W3 X' ? iscrowd = torch.zeros((boxes.shape[0],), dtype=torch.int64) / J" B1 N8 x& C: {0 p% w$ {/ e( z% t, r/ R% t( D% @, [* D$ ~
4 K; ~9 J! U; z' `4 I6 N. w labels = torch.as_tensor(labels, dtype=torch.int64) & n) T p+ H% P& w7 J% |& M w0 x) ]; y1 }. O