数学建模社区-数学中国

标题: 深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提... [打印本页]

作者: 杨利霞    时间: 2021-7-14 15:18
标题: 深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提...
$ |5 [: H" {" L* c9 |. |
深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提取图像信息
9 P# r1 R2 u% B; @% I图像标注主要用于创建数据集进行图片的标注。本篇博客将推荐一款非常实用的图片标注工具LabelImg,重点介绍其安装使用过程。如果想简单点,请直接下载打包版(下载地址见结尾),无需编译,直接打开即可!
4 \9 Q' M( U6 R# x7 @. o2 [/ \$ h  G& C) W6 I3 |2 ^% h

0 n( R7 v" U. u感谢原作者对Github的贡献,博主发现软件已经更新,可以关注最新版本。这个工具是一个用 Python 和 Qt 编写的完整的图形界面。最有意思的是,它的标注信息可以直接转换成XML文件,这和PASCAL VOC和ImageNet使用的XML是一样的。
3 l1 b" a6 a! m* {& r; L9 k% b+ h/ c

2 J% T: \" [* g  [4 `附注。作者在5月份更新了代码,现在最新版本号是1.3.0,博主亲测,源码在Windows 10和Ubuntu 16.04上正常运行。
+ \' t+ C+ ^3 H! Z$ k% u9 d7 u. V, T' h5 }6 C

3 q3 M2 A1 x* A2 b具体的安装查看Github教程:https://github.com/wkentaro/labelme/#installation
1 i, g$ g) W! Q+ l# z! n- g
  ~* o- I9 J4 [8 G# a8 }# I

, W( H$ p; D9 U& O5 L在原作者的github下载源码:https://github.com/tzutalin/labelImg
' V, Q5 K' }3 _9 K。解压名为labelImg-master的文件夹,进入当前目录的命令行窗口,输入如下语句依次打开软件。
4 j; ?7 @1 H! |5 C4 J0 ~- s/ [# E1 w1 o5 o2 B/ X) z

8 N2 f: w9 D, V, ]5 \6 zpython labelImg.py; o, C9 T6 y" j5 e& H
1! M% S+ h/ m  B4 O0 B1 F* p+ e

' i8 {& f. v$ V% s( a
; k8 V' B% x" z- o9 i* h

0 |% h& \+ \$ m* v
0 t' G6 |" o! @2 x% t. ^
具体使用, Z/ N+ P' q, F/ v
修改默认的XML文件保存位置,使用快捷键“Ctrl+R”,更改为自定义位置,这里的路径一定不能包含中文,否则不会保存。$ l% `9 M" ^- `8 Q$ e

& o7 r; V' b. p7 I" O. J+ ?# u

: l5 r! U3 L1 k使用notepad++打开源文件夹中的data/predefined_classes.txt,修改默认分类,如person、car、motorcycle这三个分类。& L8 _  o+ z. |. r, `1 n
6 A. G9 W* ^* `- }* H' @5 p' E3 q
8 J8 z$ C6 f: ^
“打开目录”打开图片文件夹,选择第一张图片开始标注,用“创建矩形框”或“Ctrl+N”启动框,点击结束框,双击选择类别。完成一张图片点击“保存”保存后,XML文件已经保存到本地了。单击“下一张图片”转到下一张图片。
2 y7 T: J' M: T$ M
! q4 y& w/ t% K

9 A  o+ r3 L+ @! ]7 \* X" Y贴标过程可以随时返回修改,保存的文件会覆盖上一个。- a( X- b* Z' S9 n* B% d  M& U4 z

5 q6 P6 I. {8 W* C7 ]5 o/ {9 y
- O3 A3 Z) [9 j: T6 \5 Z, U) P
完成注解后,打开XML文件,发现和PASCAL VOC格式一样。
7 a' V. H  q% @) m
8 F8 w. v  @& N! t4 i+ ^2 p. d
) y, R5 j! n1 w( `
将xml文件提取图像信息, F4 ?# s; R6 }. ^) m7 I. q% O, u& q
下面列举如何将xml文件提取图像信息,图片保存到image文件夹,xml保存标注内容。图片和标注的文件名字一样的。
- x5 C9 d. S9 q- k+ M9 z8 {) F* \& u  @  ]
* r# {0 f8 f" G$ M! a* V! @
# `9 x4 O0 y( t/ l4 e# s5 Q
) U1 T9 g2 ^( @
下面是images图片中的一个。2 N0 @* x6 G( L( h5 h
. ?, O- S& z( p) a- i

$ E3 f, {7 S* k% X  p) k下面是对应的xml文件。# _8 k/ d" b* N1 ~5 z+ Q

; s, z  ^8 f% T+ c; I" v

6 D3 `' ]+ l$ {7 L' J<annotation>
8 u# B$ M& J: K7 z/ I* b        <folder>train</folder>8 _8 c( |' P. W3 _9 V: t
        <filename>apple_30.jpg</filename>
+ L3 H* v" Y" ?: |& E        <path>C:\tensorflow1\models\research\object_detection\images\train\apple_30.jpg</path>3 {2 `1 |6 L4 W$ n
        <source>+ ?$ _3 E9 n9 k: Q
                <database>Unknown</database>
& p7 T4 S) @. K8 i2 g        </source>
/ L/ g3 V- X. R' v6 d& |        <size>" ]8 A) \/ e# \  A8 @/ p2 O
                <width>800</width>, R, x& t" ~. o! C. Q4 g7 F
                <height>800</height>
( E$ K$ F9 [6 t, c4 a* c  ^                <depth>3</depth>
: k2 f+ D0 g: E5 c: `7 N        </size>
: ?% o8 Q7 p- H        <segmented>0</segmented>% X! U0 s: v) H: I/ [9 t  N7 [( ^+ n
        <object>3 B) h7 h9 v6 }3 [3 }" r: G
                <name>apple</name>
' Z: L' ?3 ]/ K" r* A                <pose>Unspecified</pose>$ ?/ s* \" ~. k
                <truncated>0</truncated>* K" F! S' e1 D. e! S  W
                <difficult>0</difficult>9 k( q6 y; k, j+ d8 `& @
                <bndbox>/ L0 ?: X- U' q& x1 u
                        <xmin>254</xmin>& n6 v" V( ]! k0 H0 m+ m, s
                        <ymin>163</ymin>: Q( J3 t- U& j9 e" g, u
                        <xmax>582</xmax>& [+ H5 G! l7 z# ?
                        <ymax>487</ymax>
# N& {8 p! V; M5 f; n% y                </bndbox>
+ s! U! ^. e* d! W  f$ D) R; {9 J        </object>
3 Y* |6 w+ c, c) t% f! \, w        <object>5 q$ k) r; D! H1 R& J' ~
                <name>apple</name>) `$ n( c7 ?+ T- J
                <pose>Unspecified</pose>) F9 o+ e, l/ x6 b
                <truncated>0</truncated>
# s. R* i" A6 i1 q7 B                <difficult>0</difficult>- d: M+ t) L4 ^* h9 o
                <bndbox>8 S# E9 v+ i0 K. ]/ _& y  |9 q
                        <xmin>217</xmin>0 B# U& W- w3 d$ a4 Z& x
                        <ymin>448</ymin>) N' x3 H9 A% @6 G* b
                        <xmax>535</xmax>
" t1 h4 v- O% m* P" y                        <ymax>713</ymax># Y! t% Y2 Y% H5 A+ B: ~- p
                </bndbox>) K( b3 ~, r- d# o" b, E0 ~- K
        </object>" ^1 d6 p7 a- K; o6 j' R+ U7 L4 d
        <object>$ s  Q1 x. G5 A/ l1 X& a
                <name>apple</name>
2 k1 y( l2 e* S  T6 \  k: z0 f                <pose>Unspecified</pose>
% {, Q; Z: g) L2 ?: W! t5 s                <truncated>1</truncated>
& A6 B+ p% U8 b$ W' g* o                <difficult>0</difficult>* A, l( ^: U3 g9 f2 c5 ~% L# j
                <bndbox>
7 v" Y9 s7 ~9 S* j0 m) o                        <xmin>603</xmin>
! {0 p8 R  U4 m, U' V                        <ymin>470</ymin>
' o8 c3 a2 Y7 c. E0 S; k/ v2 k* t                        <xmax>800</xmax>
" Q- D. V" J+ V6 {6 N- U' j( l                        <ymax>716</ymax>
+ @) {3 X# u( x$ ^4 v! K                </bndbox>5 R6 L* ?0 Z4 f4 u
        </object>; M% ?5 M% s" m2 }' U
        <object>
* g, c6 {- |6 x                <name>apple</name>6 @" `1 `% z5 G, j/ F7 x' I
                <pose>Unspecified</pose>
9 {1 t9 T/ p( o. u! G2 D9 j                <truncated>0</truncated>
; ?4 ^: b) d, K: Y3 A                <difficult>0</difficult>
' D+ I. j( f, h9 p                <bndbox>
: ?( S/ T6 o, b! h* `$ B" u                        <xmin>468</xmin>
/ W; K1 D; a# j: ]; l, v7 a2 ?8 n                        <ymin>179</ymin>' l# ~5 k. w( M
                        <xmax>727</xmax>
1 O. e7 j5 q& f' I                        <ymax>467</ymax>
( ?( ~' G2 q3 W& W* y0 Q6 F$ m                </bndbox>* _# ^. |; q4 X, S( q: V& S# `
        </object>) U8 {% n/ U4 O
        <object>
8 _, ~# W% w+ a, P                <name>apple</name>
5 ^% Y' W6 G1 C+ _; l                <pose>Unspecified</pose>
5 C( Q% _4 e" y3 U7 K                <truncated>1</truncated>7 F: L& D3 n% C6 m1 a
                <difficult>0</difficult>
; _5 f& i; C7 c* M: a! l                <bndbox>' X& I5 {  a( [
                        <xmin>1</xmin>
0 S5 y- b) R5 j: d+ d                        <ymin>63</ymin>- L& `! P4 E6 L: A( r
                        <xmax>308</xmax>
. m  Q0 O/ e% Y7 z( G. z8 S5 n                        <ymax>414</ymax>: g7 E5 D1 w& {7 h( u* |( [. f
                </bndbox>* D  O$ N" Y# V# a5 V
        </object>
) J8 y. @& F: Y- D+ b7 W</annotation>- Y6 T/ t0 `( M( n
1
5 o0 c5 ~( p, `% T' A2; X( Y% ]& E) \$ N0 d
3' j: f  G1 k& t5 b# v1 Z" J8 r9 J
44 B' Z* n5 F3 Y+ C, `; S
5; n7 ?/ F9 l0 V
6$ U. [0 _- S2 q/ y
7
, ?9 h/ d2 R0 v. `- p8
' E, {1 R0 [* h7 F  L3 h: G' O9
" ]5 \' z4 P0 U. h: V* Q6 v10
, i5 ?( E0 ]' C% U8 L# \& Z/ N11
8 x7 A7 B  A) ]127 J5 |* ]! s* {
138 A  d' w* K) o2 F/ Q6 J9 j# G
14
, A- B* M: p  U15
! Y) i0 S! _7 v; {$ l% H160 A+ \( U) H  Q) ~$ p3 s
17
; J1 }6 l: W1 \+ _18
6 s) W/ Y9 K' S! X! c# \19: @8 U% ^. I$ P/ E8 d* H
20
' F& ~9 P, m7 i/ g$ j+ Z21
9 ~6 v  N. u) d. O  T9 v, F1 z22% a% R; q8 t( L2 o
23
  C( ^4 l3 Q' h$ g24
8 {1 {1 E4 F' h3 E- t8 Z: H25
/ F" |7 O; g% z- q; x' T26
/ w) c, w. _$ [, ^3 F. W$ b* i27
6 {0 F! q1 k; ^" @& S28  [$ O; C2 g) l/ A% H
29
- }, u+ {7 k$ j% t* M" p2 N30
3 H; |1 w5 }; ?: a31
' E) Q% e: T. W# @( u& S* B323 {" k: p: V. Z+ c5 ~$ L8 t# t
33
+ J4 Q& @7 ]7 x* f' W34
; O2 V4 E( g/ t& n2 q. ]9 \( z9 ^6 Z35
# S# A* E4 H, M36
6 @2 d7 A9 f! d+ \37; O! K. G6 `& n
38& i7 {7 u+ k4 k
39' Z+ o: \1 }) h7 _0 a9 M7 t- e
403 F3 o! r/ l/ z( u7 q+ R8 o) {
410 j0 T' h. P0 x  y
42
/ K( k0 [$ V9 g' U# f6 M43
3 Q9 l, `* s0 q" S1 O44  `7 l; e9 b' D0 w9 T8 t
45
# B3 P, M  o( d* \9 V! v% y4 t46$ Y+ a: v5 O5 H  A2 c7 g
47( g( {  g+ H- d- N/ T3 {- c
48
/ r' W' o8 c3 a+ i% F$ p8 X+ q492 m5 v0 v* y( p% D; {
50
8 \% G8 O. `5 M" T; D51
6 T8 s2 a! e3 e+ V525 ~- d. I- o1 s" m, h! X$ Y
53
9 U8 w: W+ c# U6 s) @6 k54+ y9 p5 W: v; Y* P% b
55
" |  A- q& f6 h567 V8 b2 Z( |. y
57
4 \% E1 K: `, o( b8 l58
) e: E% f& i( f* `" p: O59
/ t2 H3 ^' B- ?5 s( l( {5 C. K60( S, |1 H" E* B. f0 D# {
61
: ~' |! T( t; T% t7 F! r62
/ ]& ~* `8 X& \0 ?  R, X! x: k( Z63
0 |9 r" g1 l- c  S64( Z+ k2 k& h1 Y2 }: d: o) [
65# R9 {! i# \# p. `. X! w6 f$ s
66% t! e0 J: Q0 Z+ S0 g
67
  q/ j; B* j  F& L5 w2 V68
5 q% D/ Z& }. F, l9 m. J: G8 A69
# R$ S- u6 \, q6 G8 a/ m: Y70
# i+ h; f3 }7 V5 z) h712 E) y1 i& U1 x1 J' E
723 w& x$ P7 c9 `/ W+ T
735 a9 l6 x4 ~3 m8 }6 R2 p# R6 b
74
! V" c/ p. T. W将xml文件提取图像信息,主要使用xml和opencv,基于torch提取,代码比较凌乱。
2 o# o" s7 {% ]% z% w' M/ Y
% |1 X  X& B9 O$ O' P
) ?6 o% g. h/ x0 ^+ ?
import os, U' w, Z9 n$ `! k$ ^& ?9 B" U
import numpy as np, T9 H% b# G/ V; M
import cv2
7 k7 z2 H: {% @! I' O8 E& j% vimport torch' ]# I  n4 m- S4 B7 I$ k
import matplotlib.patches as patches: O7 T  E- _3 D5 \7 }: \
import albumentations as A
+ c" O+ J# y8 F- {$ jfrom albumentations.pytorch.transforms import ToTensorV2
' R& M; y! K( c1 bfrom matplotlib import pyplot as plt
* g4 g9 P( {, j/ S! _from torch.utils.data import Dataset
9 L6 I' Z) ]6 d. O9 Ffrom xml.etree import ElementTree as et0 u6 W6 \$ D4 p+ D
from torchvision import transforms as torchtrans
# M+ d. L- j- a' j/ a0 M1 B4 V1 \  H8 v; a

4 D/ R9 w/ Q5 U) X4 o6 A& _8 \% [# defining the files directory and testing directory2 F5 `# `. A- I- i2 C
train_image_dir = 'train/train/image'. S/ s  D5 q6 q* c% M) q6 m9 d+ m
train_xml_dir = 'train/train/xml', Q2 m" p2 ]) R& L6 ]1 x2 u, x
# test_image_dir = 'test/test/image'# j% E: R' }! U8 J( Q
# test_xml_dir = 'test/test/xml'% l+ s+ ?8 |. u$ T
4 V9 E! l7 f( X" ~% ^
5 n# ?, `# s# j7 N. B# r# l
class FruitImagesDataset(Dataset):; h4 O" D" B6 t6 s

8 N2 j6 v5 L0 x

4 K* ?+ m! t( A# K/ J    def __init__(self, image_dir, xml_dir, width, height, transforms=None):
5 ?; \" H1 M* o/ _6 c- T        self.transforms = transforms# a' R2 q, s* J4 s
        self.image_dir = image_dir
3 M% O! F/ ~  O  ]        self.xml_dir = xml_dir
% u% ~; D$ g2 I' b8 q        self.height = height- R! V9 o$ E  q$ ^8 \- F7 T
        self.width = width
$ v% i  Y7 o& i5 N! \7 N6 F, X7 g0 ~6 `- A% G: G# M$ ^% X
8 o9 `! z3 T( ~! {0 c' w
        # sorting the images for consistency, V6 \" D$ k/ a2 ~. s
        # To get images, the extension of the filename is checked to be jpg
. I  w# o4 P" |        self.imgs = [image for image in os.listdir(self.image_dir)1 F8 Q( w  N9 R  ~" a- l! F* ]
                     if image[-4:] == '.jpg']) U; A! F' S$ f9 y( I: b* K' s
        self.xmls = [xml for xml in os.listdir(self.xml_dir)
+ Y5 O$ r! \3 ?! v7 r7 P                     if xml[-4:] == '.xml']
* m% m! x2 L9 C) v' H3 y9 @* {9 i6 n7 l* g) z
1 h' Q  c; U& U, v
        # classes: 0 index is reserved for background0 Q( W) s3 j5 u& _3 P7 N1 w0 B
        self.classes = ['apple', 'banana', 'orange']8 x7 e2 I0 w: e, y$ t

  l" @/ e, o; `; P2 n- Y$ A4 V
, W4 O+ k. {9 G
    def __getitem__(self, idx):
( E3 W2 x' T7 j+ i, c  V
# N+ y) h7 V/ ^: ]
& M$ J9 z" }. m
        img_name = self.imgs[idx]7 m' H* o! [0 c
        image_path = os.path.join(self.image_dir, img_name)% D6 [2 i! }# L5 E$ I: j

7 s. B! o4 F* [8 W3 u

1 n/ C% ?1 Z& ~+ l! D        # reading the images and converting them to correct size and color, @, P$ J- K; r6 B. v
        img = cv2.imread(image_path)+ v9 t6 T9 y% T* A/ Z- c
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32)4 W8 _( p3 S9 y. s; f" N/ P# f3 L7 X
        img_res = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA). E- L3 ~2 [& M* W( Q
        # diving by 255
; E& @% }+ c6 d* n        img_res /= 255.0
1 G- T' I* T. T* s7 v  I. U) v' C3 ?# ~% s% s9 Q1 p6 ^

1 x- j1 \- u: z' ~  y' @3 g        # annotation file1 s7 o) q2 b' h2 F
        annot_filename = img_name[:-4] + '.xml'9 U: S: X# G5 ?& r) Q* ^* i
        annot_file_path = os.path.join(self.xml_dir, annot_filename); k0 G3 e. r0 ^" h( q3 L
. i( h5 F, ^! N8 d, T; M
/ E! P3 S. h( F0 H/ [  L
        boxes = []# i- S# q2 `  G* l3 P% x' @1 _2 M
        labels = []
$ C! V5 d$ d# d        tree = et.parse(annot_file_path)+ A' t/ ~1 n- {* `" `$ h
        root = tree.getroot()
  ]- E7 X1 X9 M9 i9 w+ ^' e4 @. |2 y' e" ^1 V# R
6 ~. N, x6 \7 A7 |: Z6 |; g
        # cv2 image gives size as height x width
( f6 M: E+ J- h$ y/ L        wt = img.shape[1]
, ?- }  t8 B3 m* P5 @7 g% r, k        ht = img.shape[0]
1 d4 q1 J; p3 Z* l
2 p& c, P' ?1 P4 k0 c7 }

5 g- @# w# F8 r; V        # box coordinates for xml files are extracted and corrected for image size given8 }6 k; f# g$ v% J+ J* |) E* s! w
        for member in root.findall('object'):
! l6 ~! J( G" i8 m            labels.append(self.classes.index(member.find('name').text))
. W! }8 a+ ?% w9 V( ^# Z# G2 m/ B; y8 y& r5 r3 I/ k  g& S
* u2 b  y( f# }
            # bounding box
- U# x3 }3 {$ T) F% G/ y            xmin = int(member.find('bndbox').find('xmin').text)2 G$ D8 t9 {& @& P$ F% `* l6 B
            xmax = int(member.find('bndbox').find('xmax').text)
. V% f( U  M9 ~/ j, M
4 f9 z4 O: F  G2 s
- ]1 H5 M( y6 G$ h; E4 T8 w
            ymin = int(member.find('bndbox').find('ymin').text)
! m0 ~7 p' d$ T- y2 \; G9 P; B            ymax = int(member.find('bndbox').find('ymax').text)
$ X# E4 t7 i& x$ e( ^2 B- S6 ~0 I  X6 ?8 z; H8 P7 |. k
* ^1 T  e) O4 a: F. w  H
            xmin_corr = (xmin / wt) * self.width
' S4 N8 i% B* }& k  C# }4 f- X$ [            xmax_corr = (xmax / wt) * self.width9 U( y7 `6 K) l$ E9 M: y
            ymin_corr = (ymin / ht) * self.height. w! |$ a5 H- N( r( t
            ymax_corr = (ymax / ht) * self.height
, G+ i/ Y% B2 v7 {  B            boxes.append([xmin_corr, ymin_corr, xmax_corr, ymax_corr])# C5 V2 A8 y7 u9 f) b; k0 Q
; ]- J4 m& ]. `1 v* Q: ~/ Y
$ A: [8 X& M) @* G
        # convert boxes into a torch.Tensor3 u7 o. V: L) W/ O
        boxes = torch.as_tensor(boxes, dtype=torch.float32)2 b. [$ n, }( a$ A' d6 b* Q. C# }
  v* @& o. x) {+ w( w+ [

% T- X/ X& Q. K7 h" D3 W/ }        # getting the areas of the boxes
: j/ I! K' v4 s2 }; Q        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])
; W' G6 \4 W6 m0 q& `7 k9 t, {) }) w4 O- v! v" \: n

4 V8 p: ^9 f) O% I; M4 T/ n        # suppose all instances are not crowd
6 |  b' p$ K3 c( _        iscrowd = torch.zeros((boxes.shape[0],), dtype=torch.int64)
5 K- a9 }: E5 @5 ^
1 _" F' x/ H0 h5 b! }9 M% H2 B* Y
' S$ k0 ^' \, ^8 k
        labels = torch.as_tensor(labels, dtype=torch.int64)
( {6 [7 Y7 b  C! N) M6 P9 D. m/ X( \0 a0 V8 W+ W

# u4 G& a0 P" O7 |* D' z        target = {}" Y" m2 D8 F/ \: e7 ~. v1 M
        target["boxes"] = boxes- N" N* Q* z" q5 ^! T4 N& {
        target["labels"] = labels
/ O7 C4 g2 [1 j- i' d2 I        target["area"] = area  k* k5 `( ]+ [# @& G
        target["iscrowd"] = iscrowd
  [. ?0 {5 H4 i' w! u! x        # image_id% D) ]" y! z! G, n' \
        image_id = torch.tensor([idx])
. L( d- h% I: [5 g        target["image_id"] = image_id
9 Z7 D% t( c, f) D$ U
4 F$ @9 \) i& f# A
% D9 L2 ^  i! F& ]" K$ p
        if self.transforms:( _: w1 Q$ b$ R6 M
            sample = self.transforms(image=img_res,  ], P5 h* ]7 L2 @5 z* k! \( M
                                     bboxes=target['boxes'],: R0 p8 ]2 x; E- h
                                     labels=labels)
' l/ a" b& g( E, ~% r
+ \% ]6 ?9 R7 W# w
, B! m, {0 R# f3 v
            img_res = sample['image']
5 F0 d: k5 ?7 V/ ~            target['boxes'] = torch.Tensor(sample['bboxes'])
' C- x# _' W1 t! I2 g4 j; k+ \0 ]
2 `- w; ~- ~$ _
) Y$ O5 W& h) y% P
        return img_res, target/ J5 n- }% t6 h
+ B! B7 N: D' G' I6 q$ g
( K. h/ g# c: a% D" [" e$ T' ]9 a
    def __len__(self):
, ]* V/ e( t3 V$ Y        return len(self.imgs); V$ n" O; M7 V

" H8 \% K6 |% ~
+ j5 E. x$ l5 M2 u
# function to convert a torchtensor back to PIL image# ^$ j/ W3 a( y. d
def torch_to_pil(img):
# X) |5 j1 d; y: O) c* ^, m, @    return torchtrans.ToPILImage()(img).convert('RGB')
, p: {9 e6 C( N- s) L
, y  i9 ~7 F5 t! g. C6 M. J4 c

) `3 E! M% n3 M5 {0 _, b/ W2 ?+ g* s' K* U) k3 H: D

) ?& n- Z/ o) |/ p7 }def plot_img_bbox(img, target):7 g( X% V2 I1 v! r  D
    # plot the image and bboxes
6 `" E9 N4 g% t8 l$ M2 s+ h% c" t    fig, a = plt.subplots(1, 1)
% b! g6 t* c( o- A, a9 J    fig.set_size_inches(5, 5)
0 o0 r& R( X' d    a.imshow(img)6 }% q! Z9 B2 n) \% u
    for box in (target['boxes']):, s# i* V% Y$ U+ E* X) ^* p
        x, y, width, height = box[0], box[1], box[2] - box[0], box[3] - box[1]3 Q) h) T/ n3 b7 B3 n* X& a
        rect = patches.Rectangle((x, y),  L5 T# \8 i5 w9 ~* n* c
                                 width, height,7 y; u/ u1 p+ G0 O5 N1 d% L; v# k
                                 linewidth=2,8 D/ {2 u0 n& A5 P! j/ w# @
                                 edgecolor='r',
0 |2 c2 g+ P% j- k6 o  q1 `                                 facecolor='none')
  `: J2 T: {6 A. C' K# `5 F
# u4 b$ s7 S% w2 W  {( ]+ j

3 L6 `6 O7 a" S$ g5 E- y( A3 e        # Draw the bounding box on top of the image
1 J% M8 j8 s' A        a.add_patch(rect)
- ?+ B" d5 N0 x" u9 x- W, y) g! e    plt.show()
4 K( N  k% U; ^" _
7 p) U% H2 M, I

/ j2 i& ]2 P1 {  k0 L6 I; a" o" ^( K+ |: q/ u
( N& h9 {4 g( t* I5 l% B( x$ [  U
def get_transform(train):
' y  y$ u( K+ ^    if train:6 f+ h9 Q0 w  _& A6 s- s
        return A.Compose([
- Q8 Q! V' D( K$ B  P            A.HorizontalFlip(0.5),
) A- o3 t( v9 T9 m. Q+ S            # ToTensorV2 converts image to pytorch tensor without div by 255. l+ R. k; j7 T6 n8 [. v2 t
            ToTensorV2(p=1.0)
  C! @+ r5 {2 M5 Q9 {% q; {5 E        ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})
. C9 B" f4 [- p    else:' B6 g  ?6 s2 r6 f3 n
        return A.Compose([
/ O) B7 N4 _6 u/ ?3 f! Y. K* c3 P8 K            ToTensorV2(p=1.0)" G' _$ h2 C- y
        ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})
- I6 Z; F+ B9 ~" l, v5 @8 x. `9 P) d+ I

0 k! F2 k) W; y' B! s. i
; H7 @  x# e$ g7 U1 G0 K9 U
5 `: j0 O4 o- [; O

, t2 `: }6 u. R* |- a
  q+ p3 k) G, ]% p8 x. E; a
dataset = FruitImagesDataset(train_image_dir,train_xml_dir, 480, 480, transforms= get_transform(train=True))
( {1 M/ V$ Y3 l# F0 m% ^& X- j0 z" f4 e% W3 c
% F- h1 H9 [2 ~( A- T* N4 B
print(len(dataset))
- @. ?. E, z! `, ?1 j6 N# j# getting the image and target for a test index.  Feel free to change the index.
3 R+ N; C8 n6 g9 N3 D" b5 ]- wimg, target = dataset[29]0 D8 q8 ?8 W3 l; W
print(img.shape, '\n', target)
3 F% ^  B* K: t5 Oplot_img_bbox(torch_to_pil(img), target)
  D! p9 U- a, {; ~4 K$ l1
; r) A- N$ J4 w7 w( ~% a) m7 J2
" w1 G! k. d- J/ J1 [3: r  R- d. @8 i5 W5 E& V
4
& t8 Q. A) R! G1 R! C5
( C. c- d  O# t2 q" B6
, F! f8 Z8 f5 s8 E9 a0 Q9 v7
3 h1 }; `1 n" l5 |8* r( j6 a5 K' U' v0 |% z% Q
91 S! V9 o: o, |
10/ e0 a5 {. e2 b; t! k5 s4 X
11' \/ N8 D- ], ^( C7 }
125 m& ~7 ^9 g8 I& j* W
136 x6 p7 u9 e, w) ~" H! x
14
  C6 \7 P7 w' b, v' l  _# p) P5 A7 p15$ O8 x1 w: Q5 E; m3 R* U# d8 k
16' R' ~4 }1 b$ Y9 N$ q7 J, n1 h
17
$ k, E/ Z- [) D9 f8 m6 N& a18
4 g7 t% F2 o: p19+ K3 F6 v7 i! ^6 s" C, c
20( \0 Y1 c2 c5 E$ J( q
21- g. B2 ^! ]; d6 N! S4 e6 k7 {
229 l3 F3 X; \# A2 ?/ ]# N. C- U$ c
23# R. @( y5 P9 [! }% G. Q
24
! G" w" k' r9 z1 e5 Y2 ]25
( o% @$ E/ G2 G8 |" _/ Q- O' J" C266 l& |0 I4 O. o4 b
27
6 s9 y0 J/ ^$ h, [7 I! s% S28
9 [' n' S; g# R& e+ j29# q" G+ }$ l( g! m4 K, {* k
307 ^# t' t& f* ^- G% J2 d9 r9 I$ t1 E
31
  k8 T, x) P" I0 y+ S' L" B5 i0 Q, ?322 a$ j9 ]3 |' G4 n4 t
33, \( K1 ^. V& P* }0 U
34
# q' G, @- h) G35
9 t. f% |+ F% e" U) P) E36, o. _+ s* Q, U* Q0 z! N$ l
37
+ X* Q4 p. Z) C38
' z, G6 _. B. t  L# R39
2 n5 S3 B9 F' e. J9 Y, G/ [7 @40
5 {3 p7 ]( w9 p2 k! F410 _2 B# Y2 M) Q# r0 x/ z3 O
42
9 `$ c* ]' R6 q43; }7 {$ a0 `5 U9 h
44
8 G: T* R7 s4 H9 O" G7 ]; I45" \8 M. p! n# J* V
46
2 N4 [4 P: R+ `. v' }* A9 S47# [9 p0 x: C( e
480 H  V6 i/ T# s6 }, `( Y: g
49! e2 G8 N) a5 W( \, r
50
; u. X# r! p; ], V516 T- I3 ?+ h: S: A+ P! C
52
& O& i! Q1 M, ?; b% P1 t53
8 B& {( l2 {6 L54
& m# R" k: l0 x% w7 P8 A55
% p: L: \8 f9 k5 {56; _" D# J# }, s7 n: R5 W+ ^, A  A
57
, ^9 [$ ]$ x. C" B+ o: ?  e58
7 V) p0 P: i- R+ m59
: P. }( T' G4 T4 S! f- |60; x, k1 l8 A( @; }
61; u# _4 o6 V7 y) {- P
62
! z% `" N0 m3 ^7 Q63$ m2 D& x- H& X4 T4 s
643 c( V' R( R) J; y& I
65
3 f' b0 u; [2 \# Z- x9 M8 [66( N7 ?% v: K4 c  O( s
677 R% j) Y" F! s9 a, K
68* P2 ?2 J+ m/ J
69) w$ a3 ^3 j% q$ Z
70% n+ ]% i0 o# d1 I! H; R& D8 o5 j
71
/ E8 B6 g1 [6 P6 u72# |# J. b5 j) P' |/ b; [/ d: d
73: t. i) ^- W/ k  |  }
74
) D! S' K4 f7 ]0 i. O* T2 U' M75
9 d& N. p& B9 G, C9 d762 E! H' ]$ a' h3 H
77
% @4 |% c2 @3 r78& S9 g, _5 A* Q- x3 h6 D4 A$ e
79" j* z0 W) d* T: T. }
80
0 t+ m% D- X% E) e& u4 D81
: Q& `4 d6 O4 C82
& T4 }) D0 n1 E: L8 a83
4 i& _( n$ n. V/ E1 ]84
* f$ b; x0 q( ~" [$ F859 G! B' w4 r2 u5 p& ^$ N
86  X# w4 ^$ C' ~1 q9 x! W
87; Y7 X/ R, i# Q) R# P
88" Z- z; P0 R& y5 K2 R
89
% t; o# R1 C* Q/ e901 j) s# x- W7 p
91  n0 e9 u4 Q" Z4 P% ~. r) v& X
92
6 v9 U( B: q* z& P  N5 s$ l& W7 m93+ v7 i! F7 I( v) m
94
( N" g* s, V5 o# H- W95+ o8 L: ?8 I, L( ?& f' ~
96
) V6 V% ]8 ~! g2 [% _97
1 k2 o8 s8 N9 x9 P6 |& e2 K98
* \0 q9 G* b$ `* X999 _& }# ^! D8 M% z3 H, x
100
" c$ @7 E: ~' l( I101
+ J  Y! n; E9 H9 ?% y1023 o! l# |6 p! L5 {. g% R
103' A, K6 }3 r$ i( T
104
. N) b6 S  a/ H; m9 f- {1 q105
! p+ g! b$ A5 {+ j106
. B2 F. H; D! }4 Z107( Z! G% ^; C, q. ?5 F6 C9 S6 @
108
5 ?& g: @5 s6 K8 K3 Z3 H109
/ Q3 ]' |$ [- U8 P# t0 i110) k3 ]7 I: i: D0 Q
111
" S  v; p; M/ D* A+ y112
( E7 j6 _- |3 l# ]+ d9 {1 V! ~6 ~113
2 L+ y/ T: ?$ f1 m114. O. K8 {4 p6 m; l( P1 p% R
115
. ~! x/ }2 f  G+ S0 ?  {1165 c( a0 W* [4 x+ }
117
9 x! n# J9 j( s, A" m1 T( P118
7 G3 O8 s  t3 u9 V4 ]119  B0 v6 m' H5 A+ E
120! i- O+ `& R. r% ^
1219 x" T+ I  _# g
122
) D6 j" G1 g7 Z5 P. ^123+ ^3 w  n  f# |' I& _, ~
1241 v* t; ~6 F- s5 e& {" \
1254 X$ o* r+ k4 H3 H8 M) C  S- a+ g
126
/ R4 B4 V( t5 e( M* r127$ ?4 B  j2 S  _4 Z
128
. J6 X5 w4 q9 I1291 b5 l$ k; A4 f# d7 o" m8 Z
130( R' K! c- ~* l  w; i' A0 A
131
1 f# i3 ?& l. J1 u% X+ M& ^132
+ a% U7 ?! j$ d' k3 R: R133
/ U8 H2 M$ A/ f6 b( q1 q! y  X134
1 W) G) Z0 Z3 c* K$ |# o& Y' h* O135
! Y9 r) i. D' r" G0 ?136; h: q! D! r# g% j4 J
137
. k1 A+ h4 L/ _: L138+ b7 Z, ]# h7 K6 W7 x  A
139
1 v; U9 X6 |$ z140, f6 l, B2 M$ V% @- X! y8 F2 Q
141* ?9 d, T6 ]9 S
142
( |1 ?6 ~2 b* A- ~1435 O  ?. t5 y1 r8 b( o0 V4 w/ j+ p
144* o1 s7 o. i5 J6 N" A
145: B2 o& N, x0 m) k( O6 a1 p
146
; ?( M) p' A+ t  z+ E; [147
0 g% \6 B# J& q% K: i. p% w) H148
1 t+ i% O& i4 s7 C$ c/ G7 d149
' z/ w$ q- S4 a5 |# K0 U- a8 U150' c3 Q, e* Q8 e8 P" o8 @7 e' p
151: Q" Y8 s& O1 t; B9 N$ \
152  Z( [3 r* m; _# y. c
153
; s; r, T* o1 \# O$ ~154
" K, r2 e/ Z% X3 G# l155
8 U  i' n) Q3 Y156
6 v$ b2 t5 `# H  _& p! }) T2 x输出如下:: t+ i; i4 [; Z, f

/ u3 B5 Q% m: J) N' d* L

" P# W7 K" M6 V' h( k5 ^4 \torch.Size([3, 480, 480])
& y$ S! K1 [9 q0 f# M$ J1 g {'boxes': tensor([[130.8000,  97.8000, 327.6000, 292.2000],
* e+ Y* Y8 F* V. S9 q. |# ^        [159.0000, 268.8000, 349.8000, 427.8000],
( B# h( n% Z: f        [  0.0000, 282.0000, 118.2000, 429.6000],
$ P' i$ L" e1 [. u        [ 43.8000, 107.4000, 199.2000, 280.2000],& C: F4 c: `' [
        [295.2000,  37.8000, 479.4000, 248.4000]]), 'labels': tensor([0, 0, 0, 0, 0]), 'area': tensor([38257.9258, 30337.2012, 17446.3223, 26853.1270, 38792.5195]), 'iscrowd': tensor([0, 0, 0, 0, 0]), 'image_id': tensor([29])}
2 L) I/ r0 B" c, c0 A+ ~* S1
. N6 P# v. i4 r' @23 t9 J8 X! k! h2 b0 m# m
3) e3 [& L" C' N( l; D5 \. A5 Z
4
6 R8 P% v& z* K- w5
% i8 \/ O4 O( K0 i2 T% }5 Q4 T0 J6+ Q! S$ A* G9 j" L- n

4 p. t! Z+ E- I5 U7 C) s8 W* z) _
1 L' X  G) Z: ]* }
* @) T$ a3 [- z
. F; O& A. r% C" d% l
下载地址4 I3 r# L1 X% F! w
链接:https://pan.baidu.com/s/1QZDgeYTHyAlD2xhtJqZ-Yw
7 \6 N8 Q: v1 w& I提取码:srjn1 g7 u: q  }. J4 o; z
————————————————, z! s* H1 L/ D2 J! F  Q. g: Z  W! |
版权声明:本文为CSDN博主「刘润森!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。# S6 y3 [" E; U0 T
原文链接:https://blog.csdn.net/weixin_44510615/article/details/118496273
! O/ x$ V& B* ^6 ~
7 t6 _3 F0 ?: R1 W7 h3 Z
$ q5 r. }# t: c4 h8 K- w% C) U6 p




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5