数学建模社区-数学中国

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

作者: 杨利霞    时间: 2021-7-14 15:18
标题: 深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提...
& Z, ?0 o8 B# ~$ U5 @. p0 M8 N! }! V; Q
深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提取图像信息- x, N7 Z2 G5 d, L- a  h
图像标注主要用于创建数据集进行图片的标注。本篇博客将推荐一款非常实用的图片标注工具LabelImg,重点介绍其安装使用过程。如果想简单点,请直接下载打包版(下载地址见结尾),无需编译,直接打开即可!
2 g3 s- Z0 ^9 e9 A# M4 I) g
( x+ F* f5 _9 v
$ I: V; n( u9 |. G
感谢原作者对Github的贡献,博主发现软件已经更新,可以关注最新版本。这个工具是一个用 Python 和 Qt 编写的完整的图形界面。最有意思的是,它的标注信息可以直接转换成XML文件,这和PASCAL VOC和ImageNet使用的XML是一样的。' ?1 O1 v$ x) g- `$ j+ k: B& b
" v6 Q! @# {% N( K: j

2 p' I; }" u7 F- t附注。作者在5月份更新了代码,现在最新版本号是1.3.0,博主亲测,源码在Windows 10和Ubuntu 16.04上正常运行。& P. J: M' g2 \

6 {7 K0 q1 }7 D1 r# [# R

0 \9 y$ h4 F* U& w, N# {具体的安装查看Github教程:https://github.com/wkentaro/labelme/#installation
' d  A$ p5 U- I' b1 Z8 D) y6 f7 Y  ~$ j% p

6 i9 G6 L* Y5 G) V在原作者的github下载源码:https://github.com/tzutalin/labelImg. c; ?8 h0 G# U3 L0 p# M
。解压名为labelImg-master的文件夹,进入当前目录的命令行窗口,输入如下语句依次打开软件。( g) {5 H7 z4 J+ a, ^

1 z. r$ @5 M; L7 T2 T" ^+ A- C

( X: F! ~* i/ f9 N4 I  apython labelImg.py
" H/ v) m9 [/ v% n1; z( P# B0 C. \& o

, ?& e0 K1 T2 @( {: d

8 r; d$ {* y& e/ {8 l
6 V. A1 p" {! q: \6 ~

5 \1 b$ Q- I5 b/ G! R; J具体使用$ h, ]0 ^+ k0 @3 x% H
修改默认的XML文件保存位置,使用快捷键“Ctrl+R”,更改为自定义位置,这里的路径一定不能包含中文,否则不会保存。
4 i5 W/ Z6 G2 e2 O3 X0 `3 F. e; F5 F5 k" H  z$ o
; e) [  a4 `5 g* f* A1 L+ j, F/ S! I
使用notepad++打开源文件夹中的data/predefined_classes.txt,修改默认分类,如person、car、motorcycle这三个分类。
* [' A/ g. E4 b4 B1 p; p3 C% l9 v
  j  V3 d3 ?/ @+ m5 I5 m/ c5 y, d
" j. [" D0 q* w2 D
“打开目录”打开图片文件夹,选择第一张图片开始标注,用“创建矩形框”或“Ctrl+N”启动框,点击结束框,双击选择类别。完成一张图片点击“保存”保存后,XML文件已经保存到本地了。单击“下一张图片”转到下一张图片。. g$ {& c' U6 j1 n& D' o: q2 \4 k
2 h6 s: D* }3 T5 z- a2 s

- ?0 e8 v  E" n: V% g贴标过程可以随时返回修改,保存的文件会覆盖上一个。& d; [0 a) N/ f' P! I
% Y7 H" s$ t& }- Y

0 G! j% E2 h+ _, k完成注解后,打开XML文件,发现和PASCAL VOC格式一样。0 r7 G3 k6 f! a( F
0 X) T6 @( j8 ~6 E

2 d# R, S! b0 ^1 k4 ^9 W8 A' _将xml文件提取图像信息
' ?' R8 J6 z( R% C- S- _下面列举如何将xml文件提取图像信息,图片保存到image文件夹,xml保存标注内容。图片和标注的文件名字一样的。8 ?* L# a1 x0 V5 O7 U/ y

) a; P- s1 A$ s6 l" V4 {
3 E, w: v5 U! n% z" }( d( y7 L

, v7 i! M; H# D

: g* E: t% w* B# d2 o下面是images图片中的一个。
2 e5 e% m1 `+ P5 \8 r3 j6 t& _: x6 V4 R; h0 O4 ]8 B' [

9 T: A8 X5 u1 N- l1 C+ n( V8 \& G下面是对应的xml文件。
( b. F2 l% e. b$ n% o/ }, W* o! d$ Q& U7 g7 X7 A
" j, Z) K3 a+ N% e) k" \$ b
<annotation>9 e, S. A, U0 m' W( ~
        <folder>train</folder>  l: s/ [! Y/ O+ O
        <filename>apple_30.jpg</filename>8 d! i* c+ A/ }1 j& k7 h/ g
        <path>C:\tensorflow1\models\research\object_detection\images\train\apple_30.jpg</path>
/ G$ x$ d* T7 Z  X        <source>
/ P5 i" B, u+ y" x                <database>Unknown</database>
( t3 g5 Y" W6 n: J* ?0 b- w        </source>0 t2 \& [3 g( {  [2 N/ X
        <size>- d4 x# o  Q! \3 ?' h9 j/ ^# P
                <width>800</width>: b- Q, `, @3 Y% u3 b
                <height>800</height>
8 Q0 _1 t5 p: r6 p8 L9 b5 j) X& z  A                <depth>3</depth>5 t  j7 G, @& i+ j* C
        </size>! k( n. n' @- c% F
        <segmented>0</segmented>
/ k+ F, j8 b( q. n        <object>
" g; e4 v7 I+ [) \7 H                <name>apple</name>2 \0 L  ~& ]9 q' S$ y/ m
                <pose>Unspecified</pose># m* v: F; Q: ^; b# d' h
                <truncated>0</truncated>
* Z7 a5 N& X% |( b                <difficult>0</difficult>
5 }5 p0 K3 o  i                <bndbox>- ]% E& ^# \) ^: k4 _
                        <xmin>254</xmin>( H& x* h  v% x% L6 v; M. I0 N
                        <ymin>163</ymin>
2 M, ~# B" N) Z9 c                        <xmax>582</xmax>
3 i6 f3 t" {8 d* @8 ?2 k                        <ymax>487</ymax>
% D0 n! D; v. U! c                </bndbox>
, |9 C$ f* t7 J4 m+ P        </object>/ \9 w0 y/ F! m" K4 {/ l
        <object>
) b4 j; T# o4 U6 Z6 S                <name>apple</name>
! Y' m( U6 m8 G4 @1 q5 Z0 t5 Y                <pose>Unspecified</pose>- I8 q" F3 ]: q6 M
                <truncated>0</truncated>
& |1 Z% i( j. }                <difficult>0</difficult>
/ J- I% t/ v, R( {                <bndbox>3 F1 ]3 T+ s, h  w. f- T5 R
                        <xmin>217</xmin>
. q/ [7 |! Y5 a. H                        <ymin>448</ymin>; H2 v& c0 n0 c
                        <xmax>535</xmax>
7 ~& ]4 h0 H- Y6 ~                        <ymax>713</ymax>
. S& P& A8 N7 E0 q' J; z  a( z, ]                </bndbox>2 g* i9 K! s" U/ z) I  Y
        </object>: A* Y1 Y$ u$ D6 R! W, @' z+ ]
        <object>* F+ d' V; B% e  V6 r
                <name>apple</name>% M" b9 d1 ?% ^' d, A
                <pose>Unspecified</pose>
: |$ V7 X& q6 y" Q7 S, G! e* v                <truncated>1</truncated>4 R/ {' k8 ~* Z9 l1 U
                <difficult>0</difficult>
( {7 g' e" b" G; m                <bndbox>
* v- w5 f$ [0 {0 W                        <xmin>603</xmin># T: R5 H1 y: |* G5 C* P, S% p) X9 _
                        <ymin>470</ymin>6 F+ w; i1 q% r' O8 i
                        <xmax>800</xmax>
$ d$ ?; F9 ^, [                        <ymax>716</ymax>% W1 J( H* \8 N4 g: Z
                </bndbox>
- ]9 B# q& R& [" j% p* P' b        </object>
; O6 s9 }1 P0 s' V        <object>
2 ?! R; K' b0 h                <name>apple</name>
( }% f4 H1 L( G8 ~; m0 Y                <pose>Unspecified</pose>5 `2 k# W0 x: X! u- e
                <truncated>0</truncated>* T( x: i  H, |0 U# m1 A0 i5 j
                <difficult>0</difficult>2 ], `3 t5 T$ \3 p
                <bndbox>
+ W, \8 l8 Q' `# t+ d( R, @                        <xmin>468</xmin>% D: @9 g6 S0 t( |) E
                        <ymin>179</ymin>
. b. M; l1 I! N- q                        <xmax>727</xmax>, u* F3 c1 c8 m% q
                        <ymax>467</ymax>
, f3 K) e% z3 `! r, g                </bndbox>
% b% ]/ }( f. d1 ]# J        </object>
$ m# c/ P: |' ]* h7 g        <object>  C7 n1 m7 X  Z
                <name>apple</name>+ w9 Z8 U8 U/ f" K% }8 i; o5 r
                <pose>Unspecified</pose>
! M+ B2 ?, T- V5 ]                <truncated>1</truncated>( f% {: m" Y. O8 o/ r6 _" p- ^3 _. @
                <difficult>0</difficult>
0 Z2 }/ R% @+ n7 p6 Q* Q                <bndbox>
# U" }0 Z% Q8 Q# V) g4 K                        <xmin>1</xmin>: i+ y2 b4 Y5 A( P+ W" ?
                        <ymin>63</ymin>
; M* d" z& @2 l5 u# |7 D& @; A                        <xmax>308</xmax>+ c) b/ y, `, n
                        <ymax>414</ymax>
( ?& H" f" j6 H: t; R, u1 ?8 ^. p                </bndbox>
0 G- d( f7 [. N6 Z( ~0 u/ W, V- g        </object>8 M. Y0 T( j* P! k) E2 V* \
</annotation>% g  y1 t' }/ u; M
1
( c' _% {# D, ^7 f; m2( m% ^# |9 ]% G" q* j" ]+ N4 f
3
' x- @6 o/ o5 b1 L3 m4
6 R( j1 k: o2 L* n" h  r- ?5
1 |# B: Y1 M; r# P" g6+ w' h2 y; ?# a! W6 T; z/ u
7
3 a: S, q1 D) _# l5 k8# E" J, O9 E5 `2 f7 |
9
% C/ ?0 J6 n/ |3 N- |101 X1 S; K9 X3 ~: w5 e! D
11
0 C- O+ F4 F) g' g# L7 ~. q12& M! \5 c( N& q8 j. s' \
13
7 K2 T' p: c0 _14$ d6 \- d# u" Z+ X0 X
15
9 A- z6 R8 }6 f' n16
3 L" @2 A% s2 p2 f* G6 G( q17
3 S; N( H" R6 o8 j; I9 T* |18& p- z' x0 q$ L7 \- E/ z7 r5 }. l9 o
19
# \$ T: U) U" T7 t( t. {3 s- z20
, m% a5 X: W" ^$ i217 v3 z" k/ s( p1 k$ o
22
) d1 r# A; c+ ]9 \# p: O: G; e, c3 @23& S; M* c9 [2 V, }, X
24
- B5 j  u" z' G2 L25
" m% u8 v6 C& M" Y( r& x9 `26) U/ `3 I$ c& j7 F( R
27$ {( Q9 Y1 Q% `1 O
28
! k/ p* d6 O. y; m' j6 X  W29
/ R6 X, r9 V2 P- o! t$ l30
1 X! E5 a0 q7 E/ }2 X; N) g) s5 b+ E31
' L- I' q! T+ ]* E8 T+ f32( n4 f3 C/ ~( G3 y( h3 T
33' w& Y& c2 p% V
34
0 A' e" P- v  l2 B2 i: q3 V35
! e; A" f+ d, C$ P/ W5 [360 Q4 i) j8 o3 M( Z2 A; M  O
37# R3 F( T9 _8 ^/ f1 n& \8 s
38
- y! t, w/ B# V0 I; T% I39% ?8 c4 v5 r6 n) _% ]2 X
40" N: _, `6 O3 t5 \- T- y  G
414 h; P: `4 E8 P, e! ^( d" q- I
42
% V  D' d! M- h6 @% n1 q43  N5 r! G: e1 l& I. D, F9 ]0 U
44
/ m1 H2 X' I8 a" \! ]45
2 Z# K9 U- u8 I, ?$ m# v  I  V* H- e46
' Q. H8 k# S: r  E5 q47
/ n1 n0 i9 h) ~7 v3 ^48. P( M% a7 R1 w& `& {/ Y
49
, u% L" |. }0 A, @) b7 q) J) r50
! T  R% a1 E  i8 Q9 u! L51/ @3 D0 X% q5 \( T% O( G  y  H' J
52) ]2 e* b/ O, u4 d! y
53
, _4 r2 \- L0 {/ g. J54
1 O" a6 j4 d! P, c8 C5 i55
; M0 ]# i" h$ z2 N# Q& C$ a56. `+ G" q6 Q  m! c/ {
57, _6 S5 z( U! ]
58% E9 ^  y+ g3 K
59
3 @( W; R! _9 S! y- x  f6 q! K60
4 K7 }, s0 s8 E+ y61
$ K; O8 }( t6 X+ P4 ?4 d62: ~% I- s' [( s
63
% Q$ G/ t! M7 E$ C% _  u9 a64
$ V, t3 I& e/ p1 y$ m  z65
2 {0 W4 k: N) D- q# S66
# I! q$ a9 s" m3 H6 t( @" d673 m0 V- C1 r+ Q4 b3 l
68
5 K$ E/ D$ P, J0 ^+ r: z; e- s- p; m69. c9 N+ U) L- O
70" @/ [% h4 N5 B  S/ d) i
716 O! N  [/ O3 \) e; q2 A
72
' H9 c* u% B% j4 O8 B; w3 @73# u: e0 z9 N: a6 y! A
74
$ ~; P+ w: @7 T8 e' N1 p将xml文件提取图像信息,主要使用xml和opencv,基于torch提取,代码比较凌乱。$ {/ Y0 d  m8 L7 H$ D" d

% Z4 a8 j3 L6 j: g8 d
# K$ l0 e1 Z" C6 \$ [) I
import os
$ @' j$ ^: n) l4 fimport numpy as np- c: g6 a; U0 ]: Q7 |
import cv2* C& W- v4 N) q3 Z- j
import torch
: D* a" ^. a. Simport matplotlib.patches as patches  n2 z, @" a& p5 A
import albumentations as A
0 z$ o- T& i, t( v9 D8 Mfrom albumentations.pytorch.transforms import ToTensorV27 t' b5 J1 b) t% v% L
from matplotlib import pyplot as plt
. ]8 ]* F: p+ c! [from torch.utils.data import Dataset
/ k1 M" ?! S. H( Y+ tfrom xml.etree import ElementTree as et
; _- q. v1 N" `- ufrom torchvision import transforms as torchtrans' Z1 y. c! }2 r& v
. B( o4 g. q1 l* w

9 e; C* m" r% a9 |3 J# defining the files directory and testing directory
5 [' h7 }! J: R' i+ c7 m2 M7 Etrain_image_dir = 'train/train/image'
5 o" r2 l2 o' @, i& Y3 i  wtrain_xml_dir = 'train/train/xml'# P. }9 ]7 U6 ]0 Q
# test_image_dir = 'test/test/image'
, s# A  Z. F6 J! M$ ?# test_xml_dir = 'test/test/xml'
: r. c7 y& P" u
" k% {. H+ @$ t% V4 E" @

2 d) _. a' u1 s5 R) iclass FruitImagesDataset(Dataset):: H. ~* S3 q: {3 M
; F( i7 t. c$ ?8 o

4 Y" @: H! ]. l    def __init__(self, image_dir, xml_dir, width, height, transforms=None):
' e! X0 m$ y. m( ^        self.transforms = transforms: {, E8 v$ E# d2 s1 d4 D
        self.image_dir = image_dir
: x; ?1 k6 m" q7 t        self.xml_dir = xml_dir
) J5 }$ D- G5 Q( ~, G2 T/ q6 e6 {        self.height = height
( w, x' H' |* g6 j+ T        self.width = width0 w9 \4 r- {# ^4 `

- h2 r# t6 b! u$ \3 }. ?

& O0 J  m* l. @& w        # sorting the images for consistency
' {# r$ m- _( K# ^) r! N" M        # To get images, the extension of the filename is checked to be jpg
9 G, K! j$ ^1 G6 f! L3 O2 S        self.imgs = [image for image in os.listdir(self.image_dir)
  W, A8 b2 E) q7 O, G- e7 _8 y                     if image[-4:] == '.jpg']; p, t! u( R1 s( k/ K& c8 r2 K
        self.xmls = [xml for xml in os.listdir(self.xml_dir)" m" h% w% R. b/ C5 ~1 G8 v" p
                     if xml[-4:] == '.xml']2 k4 j' J3 G# g  z: b1 c" C
3 q# z4 f, _; ~" f  f4 ~3 G

6 U8 @1 `( G# D& ]. a+ i  @        # classes: 0 index is reserved for background
3 L% [% G: Y; o. r! e% ~& {        self.classes = ['apple', 'banana', 'orange']
& T& M3 g1 g* ^, [
3 D. F1 N0 }- d/ U5 U, ^, N. Q
4 V% K9 J; R5 U5 i7 G. E
    def __getitem__(self, idx):
) H6 h/ ]5 c1 ?4 |' u" Q' w2 H  c$ x2 k

& G' w6 K5 H: g$ N: o4 ~2 K        img_name = self.imgs[idx]
5 f  o1 y$ [2 R: C: o+ B        image_path = os.path.join(self.image_dir, img_name)3 p3 B5 a- ^  r- h& ]; ?- H4 s
- }, X6 B" Z. @, t4 Y& w
/ h4 Z: e  C7 C. c; `
        # reading the images and converting them to correct size and color
$ L- I! K3 {: X; l; [: N- ^        img = cv2.imread(image_path)
  ~) E5 M+ K9 _# c" H        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32): ^5 C: Q/ f4 U+ k( _$ x
        img_res = cv2.resize(img_rgb, (self.width, self.height), cv2.INTER_AREA)
0 C- s1 d0 @, U. h$ X. S/ U        # diving by 255
9 Z2 \$ s" ]( C# P        img_res /= 255.0
* G& ^) C$ v6 d4 J7 G, E) ]3 e+ k; J; ?/ T: s7 j$ g+ N

; d( J( J! f3 H4 M# {        # annotation file
0 Q6 y1 D' _2 B' s& _/ D        annot_filename = img_name[:-4] + '.xml'4 ^7 f4 K$ c1 Z1 ~3 }
        annot_file_path = os.path.join(self.xml_dir, annot_filename)! C! u/ `" _# _* ~

6 d. B9 W% C6 s
' p/ _; U% H; q0 P* p" V; y7 b
        boxes = []
5 }! D" ?" O8 F* P# s        labels = []! W, J* c9 J5 m; o
        tree = et.parse(annot_file_path)3 ]3 A$ O8 P& M4 K5 C0 E
        root = tree.getroot()
, F+ ^/ ]! m- s, G" B- q: h4 S; D; O  ~" Z& e, m

# S3 Z7 m! @2 C: ?" n* w, s        # cv2 image gives size as height x width
4 C$ I1 r3 N0 D+ R( Z        wt = img.shape[1]
. i& D5 L$ A4 z6 p# Y- H9 ~        ht = img.shape[0]; a. Q' X1 |5 [% e6 u+ M

: v0 [  A+ d* j- m% v6 y. P/ h
% o2 ]: l( W* i0 Y9 t5 o' A" S2 P
        # box coordinates for xml files are extracted and corrected for image size given' Y) b7 f2 R2 }, B1 C8 q) G
        for member in root.findall('object'):
' C! v# _2 }* b% p- w            labels.append(self.classes.index(member.find('name').text))
0 E6 N  B) |  N& d3 ]/ P& d5 _
7 t( S1 p# @6 L" _# D
; g6 _' T$ m4 o( c$ T" r
            # bounding box% _- T8 Z( ?6 j7 w' w$ n8 z+ r; o
            xmin = int(member.find('bndbox').find('xmin').text), i& `6 {1 I) }8 ^' D. `
            xmax = int(member.find('bndbox').find('xmax').text)
% e8 F% ^, K- y; D  w) C. b
! w( z: F5 x2 |5 w

, w( k9 H0 X2 [% K, C) h            ymin = int(member.find('bndbox').find('ymin').text)
& w3 N% n& C9 M7 H1 @7 k1 N' L' U            ymax = int(member.find('bndbox').find('ymax').text)
" r* g: b0 [( D! [; B+ d0 a* V
% l) a) v4 u( f+ B! T

7 R: j8 j+ E, R; L7 O: F. S            xmin_corr = (xmin / wt) * self.width+ K3 u1 Q$ o+ @* w' x% M9 n9 c/ P, R
            xmax_corr = (xmax / wt) * self.width
6 @. A( A0 P# r/ r4 N            ymin_corr = (ymin / ht) * self.height
: B2 I1 |& I( j, h" R; o! h  a            ymax_corr = (ymax / ht) * self.height
; J" K5 E9 ^# p4 S% \7 K4 b3 f( _            boxes.append([xmin_corr, ymin_corr, xmax_corr, ymax_corr])% S9 H+ R" ^2 _

1 V& N; q  L5 v/ V
3 {) }3 `/ n! ?1 g/ d. O* Z4 Y8 z
        # convert boxes into a torch.Tensor# T  F, ]/ P- y/ |" v+ l0 {
        boxes = torch.as_tensor(boxes, dtype=torch.float32)' L9 n$ P- K  c3 k6 K8 w. ^4 Q

3 U3 N4 ]! ~9 s

- f5 J$ L2 e$ h% G. Q& X        # getting the areas of the boxes
+ j* b6 E- Y/ g! g1 f, O. t* m        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]); r$ Y' E! N0 V9 {) l/ x
7 s# n4 B( x$ F) Z6 x( _- s
, x& \4 Z/ {  c6 g" n
        # suppose all instances are not crowd& G- \2 g4 R1 X
        iscrowd = torch.zeros((boxes.shape[0],), dtype=torch.int64)
# l7 q; G0 E  E! V. ]) Y# e1 H' w# v' y' `9 H$ P2 o6 `
; a$ I/ L9 h: {/ C' e. `' [' M
        labels = torch.as_tensor(labels, dtype=torch.int64)
8 A5 v" }' @+ @7 E: [3 ?
) R" g9 d8 s4 x

, L% C! e/ S0 L5 a: {8 M        target = {}2 n' P8 J4 I& i. r1 l+ n7 A% N8 I
        target["boxes"] = boxes
3 S& ]5 H2 e" h        target["labels"] = labels
3 p$ e1 s) }' \. [6 b$ v" u9 C! W/ }        target["area"] = area, K4 b/ e" g" n- y+ y9 s) k
        target["iscrowd"] = iscrowd, g8 [! _9 W, Z) k4 ?3 _4 E
        # image_id4 V% w9 l# {, N: t+ L, l* u1 E
        image_id = torch.tensor([idx])
: U* F$ \7 U6 i( \        target["image_id"] = image_id; z0 V5 b7 j: ?2 P) l

6 t+ m2 r5 r0 r7 M& C# e

) P9 J9 l; U# ^# G; A# q$ t! o! ^        if self.transforms:$ ^' d  C; l' {
            sample = self.transforms(image=img_res,
: K' f3 Z* d* D9 a  z$ z                                     bboxes=target['boxes'],
1 \- S: P% M3 X6 O+ c, X1 d0 @                                     labels=labels)
: I: {' ]$ a5 W0 D& _0 g8 q5 J
0 C; u; V+ u$ s) |3 r
( w5 h4 A9 f8 Z
            img_res = sample['image']
  Z- R0 H6 v( L2 s0 q+ j7 I( h" V            target['boxes'] = torch.Tensor(sample['bboxes'])
% U* H/ C' y2 {- `( t
; c5 \& q- k6 Z/ p# \
/ e! ]3 C1 y" L  S+ y* L
        return img_res, target) t2 L& |% S0 m( ]$ ^9 L2 J
0 H8 Z; a: [1 p( i

/ }/ y9 a$ ~$ U# r# i; y    def __len__(self):
7 E3 H" G1 u9 ]; r3 x& x        return len(self.imgs)2 K* ~, X' g) G2 A6 D5 ~
! j7 E. _* k# ^3 a- v4 x
- B+ [7 Y6 w! E5 j8 P- M! @/ q
# function to convert a torchtensor back to PIL image. \4 H9 _) m" T* i
def torch_to_pil(img):( ~  }+ \( i. H; i  a! E7 C
    return torchtrans.ToPILImage()(img).convert('RGB')0 P& L4 o( c3 {

7 c9 {% x$ P7 ^+ R, r  B

& O; k% v, M+ u2 `, e4 D9 `1 L% B7 A& w

; ?/ g* j* k2 r6 Z; C9 W3 ldef plot_img_bbox(img, target):9 ^3 \2 a7 C/ W5 x# o9 h
    # plot the image and bboxes
8 w5 I, X9 H" t+ n    fig, a = plt.subplots(1, 1)* Y8 M. j' \3 z: t" K% b6 n
    fig.set_size_inches(5, 5)8 D0 k. n% @, J9 {; h
    a.imshow(img)) r1 J4 s* s5 X! L# n: T
    for box in (target['boxes']):
: h5 v8 Q( |: @0 x  ]  O        x, y, width, height = box[0], box[1], box[2] - box[0], box[3] - box[1]
$ M$ v4 |8 Z: @) x$ s1 R% r        rect = patches.Rectangle((x, y),: c2 R* |( ^& r: X. o6 m
                                 width, height,6 C1 c* R( o- v& K' U% E3 n
                                 linewidth=2,5 p! c+ n: F! d9 J
                                 edgecolor='r'," `) G3 F( `) B, B+ E8 M$ L! M
                                 facecolor='none')
: q$ |; F& |# Q0 ~3 z
: u% U, K) M5 s2 O, \! B2 ]& I
/ s8 Y$ W" x4 L: v. m
        # Draw the bounding box on top of the image) z0 F! J/ b8 {' P4 K0 b1 H
        a.add_patch(rect)) [, t0 m7 T/ N3 ?. Z8 q- z  J1 A" S
    plt.show()
  u7 J4 ]. b( B- s- |' f. q
0 J, G+ j2 e' @2 n
% b3 ~/ S( h( F* Z' Y
! ^1 K" Z' w8 g( w9 Y0 l+ g. q% p

2 k5 N) _( k! Y. ^9 g& m. idef get_transform(train):& }/ `9 \$ H2 o; A( \& i
    if train:! e. T$ B" o4 [. @, e  x- ]
        return A.Compose([
& S1 T* V! j) ?. K            A.HorizontalFlip(0.5),
6 [$ T$ W! z5 q# j: y            # ToTensorV2 converts image to pytorch tensor without div by 2553 f% X: F! Q$ I9 ]1 X4 ~: _$ m( m* f
            ToTensorV2(p=1.0)
: H" {6 ?6 a4 j3 _; i6 P- W        ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})8 `/ n, O8 I+ Z& c! K7 P" J& S
    else:& j* a& c! I7 Z" e& H
        return A.Compose([
3 s2 X& c) @4 W$ y0 _! e8 P+ m            ToTensorV2(p=1.0)
+ h4 ~1 d4 }' w- r+ Y+ D* ^        ], bbox_params={'format': 'pascal_voc', 'label_fields': ['labels']})8 E* A  V, [0 K! t$ n9 T# ^
& k; w: q" ^* i/ K& t- B

$ j, x- v) L; U$ c( G. R
" M. P# a: d8 A) j- j/ M

5 c+ w3 k8 h6 E5 q/ F% f" p
, U8 Q$ g( {9 v, Z: E: {% C

- d6 q( j3 K1 N) Jdataset = FruitImagesDataset(train_image_dir,train_xml_dir, 480, 480, transforms= get_transform(train=True)), a+ O) \$ g2 x; e& Z" N. v1 ^) d
4 Q, h+ M  h! T( ?3 {

$ S2 k/ J! U, _print(len(dataset))( ~* K2 `$ [) G+ U* t; i8 s
# getting the image and target for a test index.  Feel free to change the index.
8 k. d" z% s$ ?) N( pimg, target = dataset[29]
, T: i5 \1 k, M% t6 tprint(img.shape, '\n', target)) C1 g( J7 E/ K, `; K+ k
plot_img_bbox(torch_to_pil(img), target)& @8 |) |  l: k+ S; N! X6 z
1
% C/ ?% Y  o& T3 p% a1 D* `2/ k. y+ z4 w7 c! E8 }
3. ~6 |) o7 F; G. Q& X! A+ H8 A
4
4 e8 u; _4 x  K: X% V4 c5# R+ Q& L' o9 f2 Z$ A
6, e/ |( T' l) I
7
/ `- Y2 `4 A$ H& e8# P7 y7 L& z6 ~- Q) N. I) d
95 L7 j7 i, U( r+ O) b- q+ H) H2 G
10& d4 i7 |7 U8 _  P7 g* w
114 ~) Z6 m6 g0 g
124 s0 Y0 W  R$ b5 N9 s, \* V0 z
13, m, |6 O5 l1 x, O. `# U+ L
14; p2 U* I7 {7 q6 @
15
) h5 h& p6 r9 h16
+ A+ g) U. W7 `, A# H17
% F, b9 b2 v3 A$ B. F18  |- M2 a) ]; c$ W  N; }
19+ M/ S% w; p2 B
20" o# p/ }+ W0 l5 U5 O
21: y4 Z# M3 Z( [+ y
221 Q- ]6 Y, t3 x# V, C7 e
23
' |( m2 E* V/ t8 Z6 p- ]24, ^+ c$ k& M  \- Y
256 u9 d" ^; L' x2 U; p. C" p
26
$ O' ~$ P9 Z' {5 m% T27
* {, P4 v: X( X# ~' R  {282 l/ U' i' J% O* M" S( E
29& K" ~- F& H/ J) x! u3 G
30
# g) @+ L' v" k& v1 \1 ^31
- C7 Z# N' w1 R8 B( R32: Z0 L, P' _' b0 f# g0 {4 j
339 F6 N6 M5 M1 a& m
34# [4 c' [0 R2 |0 L# S" c, O
35: p, e6 g0 ~& X
36
% g. K/ E+ W4 B9 X9 b$ n37/ P$ w) ^; U& O
385 z- H: d: R# S& r6 D
399 n7 J! X, X. n$ x  t0 l; n8 O! ^* A
40
9 k7 Y: v+ `" a1 C5 j, H9 I% j4 M4 |6 o$ x41
; j: o5 K  ]* D7 s. a42
/ j9 q" z& U- P9 y43( ^# Z, h/ Q# r; @  V4 l
444 r; {0 o* @# m
45
  i3 A6 ?" t) D, \/ i) k46
3 Y9 Z) j  M) e47
# D; |5 d! ~( h  v: D0 H$ A. x48; ~4 A  J" J. t4 n
49
5 E! o$ o# V" l/ `7 V* F50
& A; k& @6 T* l+ t5 S$ q51
! C# {6 ^- W7 z1 j) V52
. ~7 O: P9 ?+ S8 ~/ m. x' m53  b- {5 V/ [; M. {
54
% q0 |( ^9 Y5 Z, I! b0 D) \55
( H: h* }( J! k56
8 d0 P+ b/ A! h) H0 A  F57' N5 C1 [* O% K' |, C* r: _; {
58% a, O2 \) F4 [+ L" e
593 `- @/ q1 j) S
60
# p) ^7 B3 I! m/ P! B  z4 {61
' A8 R$ O4 R7 K- e+ M/ e2 S4 t622 n$ g5 m# x; R9 c+ B8 a5 a+ G+ f
63
' V6 K3 q: B+ B9 U, X0 R' \64
. d" C* M1 a$ A5 B. ?3 X& }  m65! V8 M) Y, ?; z
66& x7 m5 A4 K, b4 V3 V- G6 t( ^
67/ ?) S( w+ _3 b8 K7 u* Y( O" Z
68
- z0 W; h2 z9 |7 \8 _69( q  ~/ @' W7 @
70( }8 T" g8 ?! J/ ~6 p
71
9 R. h: M8 f# H2 Q72
% Z1 A) R2 i$ e73
: F) G% }( Z$ z$ T: ]) V# v74
3 Q" _( D1 B$ C- a, x3 j8 P- t! R75
! @, f  G' ]3 c2 i0 Q" y' q: s76  M; t$ z* V8 x4 k7 i
778 {1 o) a! R+ T, R, z; P
78
$ q5 ?0 B% f/ M4 B7 _7 h79
. o' `/ c) T8 U" p80# R! ~! A' g1 x$ l2 Y& r9 F2 \% U9 j
81$ {1 J6 _2 e8 t# I# i3 j+ ]4 k
82- N* U' ?3 {  t  p# Y
83
4 M1 P( P3 U. C' g84, h& T6 B" N& p: K
85
) a1 r3 L7 D$ o" ?( I# l86, H5 e& n( d' Z" F2 Z
87
/ t) m+ b( X) r' w7 V% i, T5 B88# V$ D& A- \. n6 U; X6 t, ~+ ]0 q
89
5 F3 E/ D9 L1 k& P90
9 R2 ?2 r7 [. n# X  X  ^5 F% a91
/ P) a  ]4 S; Q/ T6 }, K) m92
$ s' w2 G. {/ r& M( t: M93
& S5 V3 Q: d% c+ d2 b3 C94
; d  f/ I( N5 O3 z95  B+ w( X1 E1 H2 J: h
96
& U6 u) W5 M7 P: q0 e6 |97
4 i3 l3 b- u7 X) {983 e$ f# T! @' U9 e3 q- A7 \( A
99
. W+ a, m) c+ a& a/ Q2 Q. Z( F1001 C( x. L) h7 x) B; X
101. J/ G2 r4 t& {& ]
102' x, F# T2 H7 g% k5 w+ L) X
103
$ N) g8 {. U1 a3 R4 X2 z4 ?104% a0 ~& ~/ U8 Y5 a
1057 |4 y9 M2 i; u
106; i/ D0 X4 f- [1 ]& S" T$ J( P1 U
107/ X9 B5 P" h) Y: O# m/ l
108$ M* {' U9 z, r: Q
109
* `3 B' `9 R8 r7 I* ]' ~% Z4 s110
# V1 y5 M, c0 q: S# x& }0 }111
3 M- x3 C$ h3 h& C+ F9 |112) v" B+ f2 ^5 |8 u8 z
113
: X! K! f5 u( b3 z0 o0 Q; M114
( K" _; L" Q& u$ ^" E( z  Y: @+ Z  X115
7 O/ p3 O2 K4 ]) R116) A. ]  |5 B+ N* U& f( a
1179 b4 f) \. S, C% X6 z$ i% R+ m( u6 m
1185 M$ N. V$ ^3 L$ O  R
119* T: q' e9 F5 @  o
1204 ~' Y2 n* y$ n1 Q
1214 _. Y" s7 d6 w4 b& r1 R9 w
122. u* D- m$ o1 \5 S0 F
123& L$ R& P( s6 a
124
- a2 ~, I7 d% ~7 z8 i125" A# S: O2 b1 N; e# c4 ~2 w
126
$ o( P0 t& H2 [3 T1 h  [127
7 B' P( j. c$ b8 L9 K) d128
* n- |$ w7 W, ^& @  G, `* X1290 W1 a$ {! B% O& v7 g7 u3 w8 N5 B
130& w$ I( s2 C5 N' M% r
131  V3 d# K6 @/ ^+ G
132% i# d2 ^' X) k' j! X% q! X
133
- t# l, I5 j! U: M) X134
7 `* r" h' h& b" Z0 F135
+ J% l& u' ~4 T! X7 E8 S1362 y; Q' k, h+ l/ L. S$ y. y: m$ j
137
6 [( r2 H# ]; ^8 t& Z138
' z/ I3 ^9 M; Q) {3 H139* i/ ~7 Z, ^" W3 v0 W5 o; |2 ^
140; ?/ j; P* v- P
141
% `" Z9 O! `* u. i5 w+ e; E6 ?9 Z142! T. J1 g0 R0 i1 w$ c- e3 ]
143
. {& w( J3 [( }$ H' Q144
2 I0 ]6 o+ `  v/ d145) w7 G4 H: O: L. }- Y
146
: e" M& x8 [* m! L147, U+ x) p0 P3 f' o- r* R
148; X: {: V$ l: d: S& \+ ^4 |9 y: X
149
/ u$ l, ?0 U; H1 R+ I$ t" n150
. O7 z; d* x. H5 U. l151
" L% U0 V% U4 f$ S" F, O1525 Z. D# P/ `$ O
153! `" H4 d/ S# m8 f$ p  S) t
154
- B" R( N4 [: l7 |+ ~155  X; D  }; S" G! ?0 A7 g
1564 u- o# S2 ?( m) v, H/ B
输出如下:
# a: ~4 D& M0 V7 a4 y$ W6 w, T2 M% V3 f  G

8 t! \& }$ `2 g- r" x2 ^6 {torch.Size([3, 480, 480]) 3 u# `  \, [5 }# m" x( B
{'boxes': tensor([[130.8000,  97.8000, 327.6000, 292.2000],
1 L& x0 E" m7 k( b" `- c2 W        [159.0000, 268.8000, 349.8000, 427.8000],: Y  G+ j, J: L3 ^5 g2 C$ j8 e
        [  0.0000, 282.0000, 118.2000, 429.6000],( F) u* O: s3 ^# B+ ~
        [ 43.8000, 107.4000, 199.2000, 280.2000],
8 e) ~2 {+ K3 Z/ `  U        [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])}
, r4 j+ `. ~# f7 A9 H12 Y. g& Z+ ^3 h! ~0 M9 l( ]
2* o0 Y& Z" a0 v7 c! h5 h4 m7 S
3
* J) W% e9 S: V1 Y% D4
) F: {6 N- Z* O5
2 i) n, r3 r3 B; G3 ^: L3 Q6
% k  }7 U1 N: g
7 T( l" s$ v. n

$ k/ S5 O/ _' [& \( I7 V  ?5 L( ~, g5 ^1 E0 k

8 Y. S0 a* o/ P0 C% e' X# w下载地址
8 O" z& k! {% H) J) `; |  G9 U链接:https://pan.baidu.com/s/1QZDgeYTHyAlD2xhtJqZ-Yw
. L0 a9 F& k) r' F" j% @/ D& F提取码:srjn
4 C6 z- E3 {! Q) @+ `————————————————
# Y+ u. T$ ~" ^) i版权声明:本文为CSDN博主「刘润森!」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
2 q; Q4 X9 z- ^! e6 u  G原文链接:https://blog.csdn.net/weixin_44510615/article/details/118496273, |' F0 I5 S0 P, O" {
& i# z  I1 \% n
/ D. H2 t2 `# K/ ~" Q/ n





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