# u2 |: e% t( E( {% N" u& o * ~: I% l6 A* Y/ b. B- t<annotation> " x( h( D2 s) M3 K& z% O! c5 T2 ], Z <folder>train</folder> r) _6 Q5 s6 d) K% e3 _
<filename>apple_30.jpg</filename> " k) z% @" [: \8 n1 R <path>C:\tensorflow1\models\research\object_detection\images\train\apple_30.jpg</path> ( _8 F2 `: x2 W- W: {) `2 j) p. y <source>& j: y4 t9 o# l/ i4 q, V8 I. o
<database>Unknown</database># P9 r" L* Y5 u+ |
</source>. X A" R" W- o, Y' {/ Q1 k4 ^
<size> 7 w, C( Y L7 N/ A0 G9 O5 x5 t <width>800</width>9 ~' ]% P6 g2 C) k) F7 d$ ?/ C! P* S+ V
<height>800</height>5 W7 T2 R: A* |
<depth>3</depth>' |9 f; a! m( L7 }+ K% W
</size>% }8 v W. H6 x$ e
<segmented>0</segmented> ) v1 V7 Y) }, n4 i; ~. \" K7 L <object>) `) s4 Q/ [1 m h% z( D
<name>apple</name> 9 d! c& k D, f$ S5 F1 g0 B' u <pose>Unspecified</pose> 8 J/ Z) ?! `% D7 I* X% h <truncated>0</truncated> * |, h( A* e0 |1 A. d <difficult>0</difficult>) i7 v/ y, b0 ]9 M' [1 R9 P- ]
<bndbox> & s# }8 k# L5 A0 w <xmin>254</xmin> & W2 l" k2 _* _/ h! M <ymin>163</ymin> 3 p b: j: P" u+ f' b' q7 M- ~ <xmax>582</xmax>& j4 u# Y H4 R, C- r1 a
<ymax>487</ymax># n4 Q# q. M+ P) J6 b
</bndbox>5 T3 A1 }6 e8 x0 B" e; n% r
</object>$ q1 ?: T, v9 J8 x
<object> " V% |" Y. B, r <name>apple</name> & o: n, z- [& q <pose>Unspecified</pose>+ S; T9 P7 L+ P8 y3 ^. P: d
<truncated>0</truncated> ' x# x" D- A! f <difficult>0</difficult> & u& R# n: \4 u <bndbox> 2 \6 f! r% u3 Z- o# @0 B2 n <xmin>217</xmin> 5 N) V! i9 l/ { <ymin>448</ymin>/ T& j L7 R* G% i, l3 M
<xmax>535</xmax>" d6 t4 e( P- E, Q* _6 B* R
<ymax>713</ymax> 2 t+ d- N8 I& R" i5 C; V </bndbox> 3 J- @8 \/ L6 O% l: u; `! i6 S </object>% R2 [$ j2 b, d y, I: X( V
<object> 2 { @* g# c! O, E+ T <name>apple</name>4 w( s* b) f9 M4 g+ k9 n
<pose>Unspecified</pose> ' y P- n1 L) }! ?' D <truncated>1</truncated># Z/ _7 F3 _$ N5 o
<difficult>0</difficult>- L& c7 h' V( E1 ~5 w5 y9 D# |
<bndbox>+ q/ U t f" K5 Q. v6 F8 R5 z
<xmin>603</xmin>- {% ~6 v4 I8 {; q
<ymin>470</ymin> & S1 J3 B2 d- B: ~/ I+ k <xmax>800</xmax>/ z( O9 t) F/ ?
<ymax>716</ymax> / Z6 Z0 m% l9 X; i </bndbox> 2 W( C5 n# l5 g0 c/ q! l </object> / }; L. Y. G9 ?1 R- X3 R <object>7 _4 E( S% Z: x3 m! O8 Y7 j
<name>apple</name> / J# z) V6 G, y0 S. R' R <pose>Unspecified</pose>, K- D8 K, H! o2 @# s f$ |
<truncated>0</truncated> / ^ k4 \5 P5 T S$ V/ H% e# G <difficult>0</difficult>' ]7 t2 {. Q8 s. n& h) Z/ I
<bndbox> * e6 ?6 r. S4 ~- @ <xmin>468</xmin> # c; @$ Y8 R; a3 r7 d <ymin>179</ymin>" J1 n6 v" j! J" f6 ^
<xmax>727</xmax>; L& L# \: K; ^
<ymax>467</ymax>% c5 `5 F! O1 s4 d' E, G% m
</bndbox> 2 C& F; p# ` D# I ~2 E' G </object> " O& C9 {2 D" y$ x <object> ' W% k# P3 \) r/ O: E <name>apple</name>% m) b/ j: ^6 A. I) R: [% K& V
<pose>Unspecified</pose> ) S2 L# y. }( ^3 ` <truncated>1</truncated>! r$ T& ~/ ]- o- L% Z! Y% U9 ^. e
<difficult>0</difficult>' c8 M( d: ~4 {6 Z' k1 f
<bndbox> 4 P' g9 Y; T1 ]+ R j& g( p% v <xmin>1</xmin>8 [( I! \& h5 J+ a2 M0 v
<ymin>63</ymin>2 v U1 } p v( W' f$ [
<xmax>308</xmax>( z- }) F! }1 b ~% Y
<ymax>414</ymax> * n1 o/ w0 G' D" c0 X' V: D% W </bndbox>1 [8 T* Q% k5 Q3 C
</object>( S' B6 z/ j L( L5 M+ m
</annotation> 0 W/ k: O$ W* \12 n6 W& a# F/ ?' Z( K5 w+ y
2( }; T6 a" R* @/ j2 V7 Y9 o
3# x z8 f: g- S, K2 M V. M
4 ' q9 T. X1 T3 p6 x' Q. X5. b3 ]% x" ]0 d7 \
6 2 y& j6 r1 `# `9 R) t5 W! _76 K$ I8 W+ f; @/ _& X7 t+ ^
8 . O. [/ @$ L1 b9% g' o5 P6 L1 S' O% {9 O/ B; f
107 r. |6 r" ?* d* }* l- N. p
11 / j6 t" C$ O) @; `12 * q% I, ^% _# I+ J7 r Q13 7 {% Q* M9 V( K& L. B( ]* u' |14$ [5 d2 _0 X- z9 w. b2 I
15: x" t7 ]0 t9 ~- c
16! | d$ e$ M2 k4 @ ~
17 4 r& n B% y6 c9 S2 W' P18$ A/ L8 B& ? Z9 a
19 6 s8 T7 E& d' j- P& D* z4 m207 [9 y, x8 O9 U# n% `# l
21 / D$ C8 O& X4 a22/ M* w) `# V9 q/ g) x
23# D; t6 }4 A8 r% U
24 f8 F! i5 N0 s2 e) V8 `7 D25 ; ~% E4 `# F* H: {! ?5 p! G* x( \26 & z. s S9 d0 o! @) q: Z271 m7 |# d- T4 r, P
28 2 r3 E, `% N$ D) G* F* ?297 l* G' F- l- E$ b
30! ^1 _' ~" I* G% r0 p
31 0 H% t2 e, g6 E! i- y32 $ j7 p3 D4 }1 j' ~" s q! C33 3 u; @7 H! W/ k6 |! |4 q34 : K! q% V( V7 U7 M/ m35 5 [" I8 ?, ]9 s! r. O; S/ Y/ q36 ) e5 w X6 x, p; j37 8 r6 L0 e. a9 u/ c1 B; i38$ E$ n& X- X2 [, n. b
399 J/ I* v, l3 O/ b
40 # |/ ?9 u$ L5 L4 |+ ?2 C41 4 l/ Y1 u0 P" _( L1 D42 ; R5 k! v% {, u+ A43 8 H# V6 e0 w- O44 ) w7 g% y6 b3 ]3 q. R8 ?452 ?% ]7 j/ f: b
46' y; p7 [( G; B2 R( n
476 R. z8 u2 J' c0 G3 `8 T0 H
482 I. [6 y; z- G+ x$ a0 D; R
49 7 ?2 |# ~3 w6 x3 X1 S* ]50 - |7 t; a6 M1 |) f& E6 `. P/ }51 5 f2 A0 w7 e$ W/ t52 x; V2 W7 F1 y- _7 i: L9 x( A; Y53: }, d$ j5 B+ s4 G; Z& f
54 0 q6 x6 M( x2 X55 - c8 {2 b, D' l- ?" V56 3 ^# a* _3 {" K" Y57( }! ?& q6 p% X
58" \4 @+ A. i" S6 t% E) v! l
59* ^/ C X( }1 d; Y- N$ J
60 $ [" a4 Q. l B' W) e5 _61$ p# H2 s6 l; Z2 W& \
62 0 K, f" x% e2 j7 m63 9 a- w2 Y2 k9 S9 W& |/ Q7 r643 b5 c; L8 d) h g$ z$ B
651 t. d, v5 Y C( R; D- R+ E
669 p9 G" _' y6 T8 C3 B: Y* B" O- R) d
67 9 ?' W _, a1 W x68$ {" g8 {: a& L! N
690 Q' s( R; i& M- G. \5 V
70 W) w( |% n2 y0 E% r71 , K% p2 y- {2 b/ X: A! A" J, s723 F1 c, X: j0 ^& l6 I7 k$ j
73 1 z- ]% z$ K. z9 ^/ B74 * I; Q; j* i1 q1 [" D5 {+ d. [- @) F将xml文件提取图像信息,主要使用xml和opencv,基于torch提取,代码比较凌乱。 % j* `+ ]9 Z! j0 \' c* z8 @6 k- V: [
' j' b. S1 c: c* {import os ; A! e% ^' j# }import numpy as np + j3 x( m! x; C9 ^import cv29 z, h% i: ? N9 e% \2 @& b
import torch 3 f9 R! j4 Q2 v: ~2 ]. i( ~import matplotlib.patches as patches+ |2 x4 @5 G$ G- u5 b4 P# a/ J+ L
import albumentations as A 3 d3 `# v, w( j0 e4 F1 b# gfrom albumentations.pytorch.transforms import ToTensorV2# ~6 t2 y& _, s% R6 y$ C+ d; R
from matplotlib import pyplot as plt, V2 u: g0 w7 t: ?4 z: N
from torch.utils.data import Dataset& A5 G( v8 j$ n. p
from xml.etree import ElementTree as et+ M; \# j% o8 v
from torchvision import transforms as torchtrans 1 @2 E" T& v+ x8 r4 j. [# ~ # j! b% e: z' H( g2 O: v8 a 9 ^$ x3 B7 N9 D+ m, H5 p# defining the files directory and testing directory ( k. E' K3 X3 [9 ~. S- ^$ l6 Strain_image_dir = 'train/train/image'4 n' S6 O( V( f- A- ]" [
train_xml_dir = 'train/train/xml': ]! t6 c# w7 A% X8 z9 Q8 X
# test_image_dir = 'test/test/image' + K9 M8 l- E3 m" ]9 C' k# test_xml_dir = 'test/test/xml'- n. e: T% S2 [2 H. w
$ k( W/ z! y; i: D
~& i' g" H7 [class FruitImagesDataset(Dataset): ; [( V8 P) Z4 P6 l8 y6 q6 @9 v8 K: P: L( b+ b
( f9 V% C. H3 }5 z* ~
def __init__(self, image_dir, xml_dir, width, height, transforms=None): ; o( ?+ x7 B3 V4 [1 h$ M9 ~: K self.transforms = transforms+ S) r1 l# K0 \, q+ Z1 n x
self.image_dir = image_dir; P* V$ e- C' x% \% W7 A
self.xml_dir = xml_dir, C2 e! w0 @9 B) K1 c
self.height = height 7 M7 Z% ^6 g5 O L% C6 c1 c! Z& w; _ self.width = width, i7 I9 E4 x0 O( m
~( l ~* ?: Y* Y4 A( }4 h# X3 d% Q, l' N1 ~; ^
# sorting the images for consistency * b+ }7 q( `! U1 w # To get images, the extension of the filename is checked to be jpg0 Y. M# K% x( o0 v7 [! A! V
self.imgs = [image for image in os.listdir(self.image_dir) & p9 J" k x+ U0 c if image[-4:] == '.jpg']$ _5 O& ~0 `8 s- ~1 [+ e6 N- G
self.xmls = [xml for xml in os.listdir(self.xml_dir) ) T0 L1 z( p c F3 j- M) i if xml[-4:] == '.xml'] & ~2 N4 `( b. p& h1 c' |, c6 ?; Q8 m4 @1 M- i p% B$ p
2 j: Z, \4 z+ ?4 W6 }
# classes: 0 index is reserved for background# e8 r; }# Z2 j. o
self.classes = ['apple', 'banana', 'orange']2 l& K) ~! F: }7 s# e; z
2 D8 y# s/ Y. v* S: ^% \- d, e ! C7 P8 E' t2 y: [# h def __getitem__(self, idx):/ E" [! B' e& o6 S3 c$ a$ X
* y6 _1 Q$ Z& n+ `8 @$ m, y' {4 C5 U) K; c5 Y% r' e+ Z
img_name = self.imgs[idx] 8 w6 s t t u. i image_path = os.path.join(self.image_dir, img_name)8 T' J1 |% X; F9 H
+ u5 ?! i3 } | c 7 N' u: J5 I% m # reading the images and converting them to correct size and color # W( \* w! m( ~$ v6 W img = cv2.imread(image_path) @6 F& s: T4 d9 ^3 ~6 Y$ o img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32) 3 j( d+ R7 @' H: C! _+ x# p img_res = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA)" y$ j4 h9 G) T
# diving by 255 ' {2 G' r Q. ~0 y$ H/ I6 J img_res /= 255.0& @+ A2 W3 J3 i+ P9 X+ t+ q
3 @8 ~1 Q& F; r- G( j6 W t
' E3 s" N, r, F& _* Z: w
# annotation file ( P. D. Z5 Y- E: X& @ annot_filename = img_name[:-4] + '.xml'/ a: V6 z! X, z4 r
annot_file_path = os.path.join(self.xml_dir, annot_filename) : A( f) ^9 O4 h9 ~ ! L3 ?. U! D6 f4 _8 p0 N, `8 `# E( Y
boxes = []) l5 g+ ~4 X x" d& C9 @- ]7 d
labels = [] 3 V; }% J* |* B% {4 X* x7 V tree = et.parse(annot_file_path)8 f0 [6 ~) C' d1 \- O) g, ?+ _
root = tree.getroot() ( G- n. K6 ]. S; P( ] 4 J% N# e, t, z- D/ n" K: ]. N% n4 U4 M- A- c
# cv2 image gives size as height x width 0 v1 V" Z8 p( v: w* j" M$ n2 W& E wt = img.shape[1] $ }+ L9 C" ?1 e ht = img.shape[0] 2 h. M2 R" e P: I2 J0 W# G) [% F4 }" V* N
: t2 P$ }7 g. w) v # box coordinates for xml files are extracted and corrected for image size given ) D; G# W8 M$ \ for member in root.findall('object'): 2 H' ?0 k$ W1 m- ]6 K labels.append(self.classes.index(member.find('name').text))( {. f2 y: D! {/ _! t
6 U9 |/ D. e3 c5 Q# I5 r
7 U/ v' K w* F9 s; l8 B% M( f
# bounding box+ } Y8 R. o, W. `5 c' k
xmin = int(member.find('bndbox').find('xmin').text) N$ h" j8 i7 t3 ^' h
xmax = int(member.find('bndbox').find('xmax').text) 8 k& z/ j, v) B4 C+ {: _# C5 @2 ?. v3 M( v$ `& K3 @8 z
* E N6 I; O1 `! b6 u! C, {$ u
ymin = int(member.find('bndbox').find('ymin').text) 4 _& A9 M: T3 I' p M, v* e ymax = int(member.find('bndbox').find('ymax').text) # }; N) P [& y! M$ L: L9 m1 w8 ?
, B7 _" J; t( `7 }7 W, o# h
xmin_corr = (xmin / wt) * self.width# ]9 W+ {1 ] B
xmax_corr = (xmax / wt) * self.width G; v1 P3 x) G' |+ ?
ymin_corr = (ymin / ht) * self.height7 J& l* I- x: N2 t( o0 n1 [
ymax_corr = (ymax / ht) * self.height/ ^/ D/ k y+ D! R3 e5 \) d8 O. Z
boxes.append([xmin_corr, ymin_corr, xmax_corr, ymax_corr])$ ^$ T7 K6 H- V
9 T" I j, s; n4 A z
, j8 ^$ W$ u) F/ l. q* e
# convert boxes into a torch.Tensor1 \0 A& a& L3 P+ {7 Q
boxes = torch.as_tensor(boxes, dtype=torch.float32) , K7 J a8 ]1 V/ q! }: R+ a : M: ]1 s5 J) I7 s0 B) U+ \) J8 m! L! o/ l8 W0 q: _
# getting the areas of the boxes 9 s4 t+ F* R) M& v! } area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]) * v5 ~$ A4 Z( p: X! {: t+ W7 _: L2 J; [$ _; a+ Z5 ~" m
Z) e$ \0 Z; T9 R o; S # suppose all instances are not crowd. Q( `7 z9 v( b# _, N% }
iscrowd = torch.zeros((boxes.shape[0],), dtype=torch.int64)/ J5 Q, Z) A& ^* K9 z! o
8 c7 W5 W* U5 Z) ]& f6 o0 U
, |" a+ u- g; s, }
labels = torch.as_tensor(labels, dtype=torch.int64) Z9 i r- c/ A! b7 W6 O
0 K2 _. V9 o. r$ Q! w4 c+ Y' _% m
6 h8 j! h. N9 ~
target = {}& W1 v3 K4 Q# l7 ?4 D& h1 b0 e
target["boxes"] = boxes # U$ k, F! j i6 B5 x4 I target["labels"] = labels % ^7 b/ C- ^6 _) ` target["area"] = area $ s4 P8 W8 D0 u4 ^. u. O' ~* J* D target["iscrowd"] = iscrowd 7 P6 J4 I8 f, J! S; F, z0 U# m # image_id0 Z2 H, ]4 ^/ Z" X
image_id = torch.tensor([idx]) * n E5 G- K; Q- a' h8 o target["image_id"] = image_id/ x1 n! E/ W/ G! u
}! Y$ z& l4 L. H2 U% P& s( G
+ x7 q: X( _: G+ j5 z. G
if self.transforms: : @, `' H! N$ C0 z; w sample = self.transforms(image=img_res, 4 k: n; n( X; H3 E. h; ~ bboxes=target['boxes'], & E3 N, o- G& C labels=labels) : e) L. L1 v# S0 G$ O0 n5 p0 m5 g8 t: f! n5 O
4 p5 b8 N+ ]+ ?8 ^& Y' E* T! J# g img_res = sample['image']. _! D( F+ j3 S
target['boxes'] = torch.Tensor(sample['bboxes']) ) f, u# [# K' r5 k( Y4 B$ K2 U: U " v7 y8 |9 l6 r8 o2 N5 l# O! l) q7 T3 j# j7 O1 V
return img_res, target# j" q" q$ |# i( W& u
4 }- h B9 p, r% _" u( U6 |+ s7 {9 i( ~4 M
def __len__(self):% X" V; [4 d& m- g
return len(self.imgs) : R* A2 K/ l2 r" K1 R: Q8 F 3 n( X8 S% R: H7 U; B$ w- R( j; L, Y8 D3 v* q/ U$ [7 Q
# function to convert a torchtensor back to PIL image# ?; `1 q9 _: H1 q# n5 C
def torch_to_pil(img): @4 @; r% P1 Y6 X4 n return torchtrans.ToPILImage()(img).convert('RGB') $ g/ W7 _3 ]+ \5 @4 ]0 W# P6 s% d o8 S3 c k
+ x) E' a% r4 T9 T5 h
0 G# c2 n ], b/ T* L( I7 [" s; \6 x
def plot_img_bbox(img, target): {# h+ y) q" B+ D5 Y' g # plot the image and bboxes; e, b% [5 Q `1 ~6 r) `0 J' H) J
fig, a = plt.subplots(1, 1)5 \( f9 z) V4 h1 M4 j! |* i9 V# V
fig.set_size_inches(5, 5)% h. F/ v; S: e: U: x
a.imshow(img) / j" m9 E- D+ |/ i b% y for box in (target['boxes']): . M1 S+ ^: A) s5 C% d9 p/ c x, y, width, height = box[0], box[1], box[2] - box[0], box[3] - box[1] $ f( e' }" `) _8 S0 Q7 r rect = patches.Rectangle((x, y), 0 w/ u @3 f* ^4 i& G0 |' d9 K width, height, ) N. W& P, _/ q4 c linewidth=2,, D9 h5 ^) C3 P: S% z
edgecolor='r', ' h2 C% T" ?% R. V facecolor='none')5 }0 ~2 c( b5 n
: k$ L9 Y& e) p0 P4 q) c % z& I, _9 u7 }$ c0 @ # Draw the bounding box on top of the image' v, _" Q6 c; B) g9 a8 Z, w
a.add_patch(rect)* y G4 X& N% o& p- n9 C
plt.show() , z( k; T/ {" B; E" t \$ x1 B% O " j# i1 q8 V$ X: q. K/ P) p- n/ a' v1 O; Y0 \
- N$ C r+ \& z! a i, {: b' r1 o' Z$ d( m. f. v0 Q! i1 u5 C( ^' I
def get_transform(train):4 [( B6 T9 p7 }7 {0 E$ Q
if train:* r4 @& C5 y& X; B9 r4 q! L
return A.Compose([ 6 q1 x; v4 M* v0 V2 z A.HorizontalFlip(0.5), 7 f! G. Y, H; |( `! J* x) } # ToTensorV2 converts image to pytorch tensor without div by 255) ~4 T. T1 `3 K0 U6 o( g9 O
ToTensorV2(p=1.0) ) J0 s' h5 ~: l4 u; d ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})4 G' W' c# J W5 ?1 ]" G
else: K- ]! M5 O' @+ p" J
return A.Compose([ 7 _% ]# H9 K' O. q5 U ToTensorV2(p=1.0) ' t/ J1 H* F* k+ Z ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']}) ' W" H' G& u% g* M, V8 {$ D" A , ?! L* R U+ q& ?" r; l % Z* y9 _% u! \7 ^) o) B- [( g) K( f5 l
Z& c, A$ k$ ?, |' ^1 V! q
1 S D1 ~' N0 v+ s1 |& V+ `