Preface
Code Zoo,就是想把我平時寫的一些代碼,如腳本工具啊什麼的,整理集中起來。供以後參考,也給需要的同學一點線索。
統計文件夾下的文件數量:
import os
import os.path
dir = "/home/chenxp/Documents/vehicleID/train/font_vehicleID"
i = 0
for root, dirs, files in os.walk(dir):
for name in files:
i = i + 1
print i
讀取 XML 文件內容
最近在忙一個比賽,主辦方給我們一個 XML 文件,我們需要根據這個 XML 文件讀取圖像的文件名這類信息。如下:
根據這個文件,再結合主辦方給的數據集,就可以根據 modelID
或者 vehicleID
標籤,把給的數據集進行分類。比如,我要根據 vehicleID
標籤把數據集按照這個 vehicleID
分類,就是把具有相同的 vehicleID
歸類到一個文件夾中。主辦方給的數據集如下:
下面就是讀取 XML 文件裏的屬性數據了,代碼如下:
# !/usr/bin/env python
# encoding-utf:8
from xml.dom.minidom import parse, parseString
import os
import glob
from PIL import Image
#outDir1 = os.path.abspath('/Users/chenxinpeng/Desktop/train/vehicleID/')
# read the images into the imglist, get the basename of images
imgNames = []
imglists = glob.glob('/home/chenxp/Documents/vehicleID/train/images/*.jpg')
for img in imglists:
imgNames.append(os.path.basename(img))
# test
print imglists[0]
# 進行 XML 文件的解析
# begin parse the xml file
dom = parse('train_gt.xml') # parse an XML file by name
# get document object
# 得到根結點
root = dom.documentElement
# 根據標籤名 Item ,得到 Item 所有的屬性及其屬性值
# 比如屬性 colorID、imageName、modelID、vehicleID
# 及這幾個屬性對應的屬性值,放入到 itemlist 中
itemlist = root.getElementsByTagName("Item")
XML_imageNames = []
XML_colorIDs = []
XML_modelIDs = []
XML_vehicleIDs = []
# 根據屬性,得到這個屬性的所有元素值,放入到 list 中
for item in itemlist:
XML_imageNames.append(item.getAttribute("imageName"))
XML_colorIDs.append(item.getAttribute("colorID"))
XML_modelIDs.append(item.getAttribute("modelID"))
XML_vehicleIDs.append(item.getAttribute("vehicleID"))
# test
print XML_imageNames[0]
print XML_colorIDs[0]
print XML_modelIDs[0]
print XML_vehicleIDs[0]
# 用 set 去除掉 XML_vehicleIDs 中所有重複的 vehicleID
shrink_XML_vehicleIDs = sorted(set(XML_vehicleIDs), key = XML_vehicleIDs.index)
print len(shrink_XML_vehicleIDs)
# 遍歷不重複的 vehicleID
for item in shrink_XML_vehicleIDs:
# 創建 vehicleID 文件夾, 裏面存放所有具有相同 vehicleID 的圖片
os.mkdir("/home/chenxp/Documents/vehicleID/vehicleID/" + item)
outDir1 = os.path.abspath('/home/chenxp/Documents/vehicleID/vehicleID/' + item)
# 用 enumerate 遍歷 XML_vehicleIDs 中所有與當前遍歷的item(vehicleID)相同的元素, 及其元素的索引
indexImg = [i for (i, v) in enumerate(XML_vehicleIDs) if v == item]
# 根據索引 list, 保存這些圖片
for imgItem in indexImg:
indexTemp = imgNames.index(XML_imageNames[imgItem]+'.jpg')
dir = imglists[indexTemp]
imgTemp = Image.open(dir)
t = os.path.basename(dir)
imgTemp.save(os.path.join(outDir1, t))
若想根據之前 XML 中的 modelID
來歸類,將具有相同 modelID
的圖像歸到一個文件夾中,代碼如下:
# !/usr/bin/env python
# encoding-utf:8
from xml.dom.minidom import parse, parseString
import os
import glob
from PIL import Image
# read the images into the imglist, get the basename of images
imgNames = []
imglists = glob.glob('/home/chenxp/Documents/vehicleID/train/images/*.jpg')
for img in imglists:
imgNames.append(os.path.basename(img))
# test
print imglists[0]
# begin parse the xml file
dom = parse('train_gt.xml') # parse an XML file by name
# get document object
root = dom.documentElement
itemlist = root.getElementsByTagName("Item")
XML_imageNames = []
XML_colorIDs = []
XML_modelIDs = []
XML_vehicleIDs = []
for item in itemlist:
XML_imageNames.append(item.getAttribute("imageName"))
XML_colorIDs.append(item.getAttribute("colorID"))
XML_modelIDs.append(item.getAttribute("modelID"))
XML_vehicleIDs.append(item.getAttribute("vehicleID"))
# test
print XML_imageNames[0]
print XML_colorIDs[0]
print XML_modelIDs[0]
print XML_vehicleIDs[0]
shrink_XML_modelIDs = sorted(set(XML_modelIDs), key = XML_modelIDs.index)
print len(shrink_XML_modelIDs)
for item in shrink_XML_modelIDs:
os.mkdir("/home/chenxp/Documents/vehicleID/attributeSame/" + item)
outDir2 = os.path.abspath('/home/chenxp/Documents/vehicleID/attributeSame/' + item)
indexModel = [i for (i, v) in enumerate(XML_modelIDs) if v == item]
for modelItem in indexModel:
indexTemp = imgNames.index(XML_imageNames[modelItem] + '.jpg')
dir = imglists[indexTemp]
imgTemp = Image.open(dir)
t = os.path.basename(dir)
imgTemp.save(os.path.join(outDir2, t))
用 python 將 TXT 文件內容寫入 XML
若我有一些 txt
文本文件,如下所示:
每個 txt
文件內容,如下內容:
現在的任務是,以這些 txt
文件的文件名爲 XML 文件裏的屬性名稱,以屬性值爲對應的 txt
文本中的所有值,用空格隔開這些值。主辦方示例如下:
<?xml version="1.0" encoding="gb2312"?>
<Message Version="1.0">
<Info evaluateType="6" mediaFile="vehicle_retrieval_val" />
<Items>
<Item imageName="012321 ">
0292851 0110741 0173591 0092564 0286241 0192567 0340982 ...
</Item>
<Item imageName="003467 ">
0387241 0023986 0283751 0230114 9806431 8823012 2389102 ...
</Item>
<Item imageName="13169 ">
3727192 0387654 0007942 0009866 0120397 0485764 1200341 ...
</Item>
......
</Items>
</Message>
生成這段 XML 的代碼如下:
import os
import os.path
import xml.etree.cElementTree as ET
srcDir = "/Users/chenxinpeng/Desktop/today/txtFile"
# 遍歷 txtFiles 文件夾下, 所有的 .txt 文件
# 將文件名放入列表: txtFiles
txtFiles = []
for root, dirs, txtNames in sorted(os.walk(srcDir)):
for txtName in txtNames:
txtFiles.append(txtName)
# 去掉 TXT 文件名的後綴(.txt)
txtFilesBase = []
for item in txtFiles:
a, b = os.path.splitext(item)
txtFilesBase.append(a)
# test
print(txtFiles)
print(txtFilesBase)
root = ET.Element("Message")
root.set('Version', '1.0')
subRoot = ET.SubElement(root, "Items")
for eachTxtFile in txtFiles:
refImgs = []
allNames = '' # 預先定義好大的字符串
# 用 with open() as f 的方式來打開文件夾
# 這樣不需要自己去 f.close(), 關閉文件
with open(os.path.join(srcDir, eachTxtFile)) as f:
# 按行讀取, 用 strip() 函數去除: '\n'
for line in f.readlines():
line = line.strip('\n')
refImgs.append(line)
# 將 refImgs 這個 list 中的元素,合併成一個大的字符串
# 並用 空格(' ') 隔開
length = len(refImgs)
for i in range(0, length):
allNames = refImgs[i] + ' ' + allNames
ET.SubElement(subRoot, "Item", imageName = txtFilesBase[txtFiles.index(eachTxtFile)]).text = allNames
tree = ET.ElementTree(root)
tree.write('vehicleID.xml')
這裏補充一下:
1. 打開文件夾的方式可以參考 stackoverflow 上的這篇回答:http://stackoverflow.com/questions/8009882/how-to-read-large-file-line-by-line-in-python
2. python 按行讀取文件,如何去掉換行符 \n
,可以參考:http://blog.csdn.net/jfkidear/article/details/7532293
3. 用 python 寫入 XML 文件,可以參考:http://stackoverflow.com/questions/3605680/creating-a-simple-xml-file-using-python,以及:https://pymotw.com/2/xml/etree/ElementTree/create.html
用 python 重命名文件
如何給一堆 TXT 文件重命名?如下,有一堆 TXT 文件:
現在我要對這些 TXT 文件,在其文件名後,加 1。即,如果文件名爲:begin56list.txt
,加 1 變成:begin56list1.txt
。
這個用 python 的 os.rename
或者 shutil 模塊可以很快的完成,如下:
import os
import sys
import shutil
Dir = '/Users/chenxinpeng/Desktop/list'
for root, dirs, files in Dir:
for item in files:
temp1, temp2 = os.path.splitext(item)
shutil.move(item, temp1 + '1.txt')
這樣就完成了,我用的是 shutil 的 shutil.move()
命令,參考 stackoverflow 的這個問答裏:http://stackoverflow.com/questions/2491222/how-to-rename-a-file-using-python
判斷文件、文件夾是否存在
python 判斷文件、文件夾是否存在就一句:
import os
os.path.isfile("test.txt") # 如果不存在就返回 False
os.path.exists("/home/chenxp/*") # 如果不存在就返回 False
去除 lists 中重複元素
現在我有一個 lists,怎樣去除其中重複的元素呢?
x = [0, 2, 2, 4, 3, 5, 6, 5, 0, 2]
# shrink_x 代表去除重複元素後的 x
shrink_x = list(set(x))
print(shrink_x)
結果見下:
不過上面的這種去除重複元素,是排序過了的。如果要想保持原來的次序:
x = [0, 2, 2, 4, 3, 5, 6, 5, 0, 2]
# shrink_x 代表去除重複元素後的 x
shrink_x = sorted(set(x), key = x.index)
print(shrink_x)
# 或者
shrink_x.sort(key = x.index)
也可以使用遍歷:
x = [0, 2, 2, 4, 3, 5, 6, 5, 0, 2]
y = []
for item in x:
if not item in y:
y.append(item)
print(y)
車輛精確檢索之 modelID、 vehicleID 問題
還是那個車輛精確檢索的任務,這回是想,將訓練圖像中 modelID 相同的同一類車,先新建一個 modelID 文件夾,然後再在 modelID 下,根據每輛車的 vehicleID ,新建 vehicleID,並將 vehicleID 相同的保存在這個文件夾。
最後的目錄結構如下:總的是叫做 train_modelID_vehicleID。之下,則是 0、1、2、4、6、7、8、10、11、12 …… 這類 modelID 文件夾,裏面的車輛都是 modelID 相同的。相同 modelID 之下,如 modelID = 6,這個 modelID 之下,有許多不同的車輛,每個文件夾名稱代表了 vehicleID,如:2413、8368、16447、26525 。
給的 XML 文件如下,裏面有 modelID、vehicleID 的信息:
那這個任務怎麼實現呢?雖然很簡答,但我相岔了,耗費了不少時間…在這裏記錄下來:
from xml.dom.minidom import parse, parseString
import os
import glob
from PIL import Image
outDir1 = os.path.abspath("/Users/chenxinpeng/Desktop/today/vehicleID/train_modelID_vehicleID")
# read the images into the imglist, get the basename of images
imgNames = []
imglists = glob.glob('/Users/chenxinpeng/Desktop/today/train_font/*.jpg')
for img in imglists:
imgNames.append(os.path.basename(img))
backNames = []
imglists2 = glob.glob('/Users/chenxinpeng/Desktop/train_back/*.jpg')
for img in imglists2:
backNames.append(os.path.basename(img))
# begin parse the xml file
dom = parse('train_gt.xml') # parse an XML file by name
# get document object
root = dom.documentElement
itemlist = root.getElementsByTagName("Item")
XML_imageNames = []
XML_colorIDs = []
XML_modelIDs = []
XML_vehicleIDs = []
for item in itemlist:
if (item.getAttribute("imageName") + '.jpg') in backNames:
continue
XML_imageNames.append(item.getAttribute("imageName"))
XML_colorIDs.append(item.getAttribute("colorID"))
XML_modelIDs.append(item.getAttribute("modelID"))
XML_vehicleIDs.append(item.getAttribute("vehicleID"))
shrink_XML_modelIDs = sorted(set(XML_modelIDs), key = XML_modelIDs.index)
shrink_XML_vehicleIDs = sorted(set(XML_vehicleIDs), key = XML_vehicleIDs.index)
# 新建 modelID 文件夾,防止後面出現 ‘no such file or directory‘ 的情況
for item in shrink_XML_modelIDs:
os.mkdir(outDir1 + item)
# 對於 每一個 vehicleID 進行遍歷
for vehicleID_item in shrink_XML_vehicleIDs:
# 找出 vehicleID 相同的所有圖像,返回它們的索引
indexVehicleID = [i for (i, v) in enumerate(XML_vehicleIDs) if (v == vehicleID_item)]
# vehicleID 相同的,其 modelID 也一定相同
# 加上 XML_vehicleIDs、XML_modelIDs 順序一樣
# 所以找到這輛車的 modelID,在這個 modelID 下新建文件夾
# 這裏的 kk 名字是隨意取的
kk = XML_vehicleIDs.index(vehicleID_item)
outDir3 = ourDir1 + XML_modelIDs[kk] + '/' + vehicleID_item
os.mkdir(outDir3)
# 對於每一張 vehicleID 相同的圖像,進行讀取並保存
for imgItem in indexVehicleID:
# vehicleID 與 圖像的 imageName 是一一對應的
indexTemp = imgNames.index(XML_imageNames[imgItem] + '.jpg')
dirTemp = imglists[indexTemp]
imgTemp = Image.open(dirTemp)
t = os.path.basename(dirTemp)
imgTemp.save(os.path.join(outDir3, t))
用 python 生成 Triplet Loss 所需要的訓練數據
Triplet Loss 生成數據需要一張 Anchor 圖像、一張 Positive 圖像、一張 Negative 圖像。如何從給定的訓練數據中自動生成呢?
from xml.dom.minidom import parse, parseString
import os
import glob
import random
from PIL import Image
#outDir1 = os.path.abspath('/Users/chenxinpeng/Desktop/train/vehicleID/')
backLists = glob.glob('/home/chenxp/Documents/vehicleID/train/train_back/*.jpg')
backNames = []
for item in backLists:
backNames.append(os.path.basename(item))
# read the images into the imglist, get the basename of images
imgNames = []
imglists = glob.glob('/home/chenxp/Documents/vehicleID/train/train_font/*.jpg')
for img in imglists:
imgNames.append(os.path.basename(img))
# test
print len(imglists)
# begin parse the xml file
dom = parse('train_gt.xml') # parse an XML file by name
# get document object
root = dom.documentElement
itemlist = root.getElementsByTagName("Item")
XML_imageNames = []
XML_colorIDs = []
XML_modelIDs = []
XML_vehicleIDs = []
for item in itemlist:
if (item.getAttribute("imageName") + '.jpg') in backNames:
continue
XML_imageNames.append(item.getAttribute("imageName"))
XML_colorIDs.append(item.getAttribute("colorID"))
XML_modelIDs.append(item.getAttribute("modelID"))
XML_vehicleIDs.append(item.getAttribute("vehicleID"))
# test
print len(XML_imageNames)
print len(XML_colorIDs)
print len(XML_modelIDs)
print len(XML_vehicleIDs)
shrink_XML_vehicleIDs = sorted(set(XML_vehicleIDs), key = XML_vehicleIDs.index)
print(len(shrink_XML_vehicleIDs))
openDir = '/home/chenxp/Documents/vehicleID/train/font_vehicleID'
fd = open('/home/chenxp/Documents/vehicleID/train/tripletImg.txt', 'w')
numFiles = []
for item in shrink_XML_vehicleIDs:
numFiles[:] = []
openDir2 = openDir + '/' + item
for root, dirs, files in os.walk(openDir2):
for itemFile in files:
numFiles.append(itemFile)
negImgTemp = []
posImgTemp = []
if len(numFiles) >= 2:
temp_shrink_XML_vehicleIDs = []
temp_shrink_XML_vehicleIDs = shrink_XML_vehicleIDs
temp_shrink_XML_vehicleIDs.remove(item)
#posImgTemp = random.sample(numFiles, 2)
negImgTemp = random.sample(temp_shrink_XML_vehicleIDs, 100)
for item2_neg_vehicleID in negImgTemp:
numFiles2 = []
numFiles2[:] = []
for root2, dirs2, files2 in os.walk(openDir + '/' + item2_neg_vehicleID):
for itemFile2 in files2:
numFiles2.append(itemFile2)
negImgTemp2 = random.sample(numFiles2, 1)
posImgTemp = random.sample(numFiles, 2)
temp1 = openDir2 + '/' + posImgTemp[0]
temp2 = openDir2 + '/' + posImgTemp[1]
fd.write(temp1)
fd.write(' ')
fd.write(temp2)
fd.write(' ')
temp3 = openDir + '/' + item2_neg_vehicleID + '/' + negImgTemp2[0]
fd.write(temp3)
fd.write('\n')
fd.close()
最後生成的 TXT 文件,其中每一行,先存儲 Anchor 圖像的絕對路徑,再存儲 Positive 圖像的絕對路徑,再存儲一張 Negative 圖像的絕對路徑。示例圖如下:
之後,生成訓練數據時,從上面的這個 TXT 文件中讀取圖像,再存儲爲 Tensor(因爲我是用的 Torch)。
查看 numpy 版本、安裝位置
2016.07.29 更新
import numpy as np
print(np.version.version)
# 或者
print(np.__version__)
# 顯示安裝位置:
print(np.__file__)
顯示如下:
反轉字符串
Python 中反轉字符串很簡單,用切片的方式一句話解決:
s = "hello world"
print(s[::-1])
輸出:
切片的語法,參考:https://docs.python.org/2/whatsnew/2.3.html#extended-slices,如下:
[begin:end:step]
如:
s = "hello world"
print s[0:4:2]
輸出爲:
通過 os 模塊獲取當前路徑
2016.09.11 更新
通過 os
模塊中的 getcwd
函數獲取當前路徑:
import os
root = os.getcwd()
print root
輸出如下:
lambda 表達式
2016.09.12 更新
lambda 表達式就是一個 匿名函數,通常 python 中定義一個函數,需要用如下方式:
def function_name(parameters)
......
但是有時候,這個定義的函數,我們僅僅使用一次。那爲了這一次的使用,而去再定義一個函數,就顯得很麻煩,多定義了一個(污染環境的)函數。
這種情況下,python 中通過 lambda
表達式支持 匿名函數 的創建。但是,Python對匿名函數的支持有限,只有一些簡單的情況下可以使用匿名函數
如下:
a = lambda x, y: x+y
print a(1,2)
還可以通過 map
做稍複雜的事情:
a = [1, 2, 3, 4, 5]
b = map(lambda x: x + 1, a)
print b
上面的兩個例子輸出結果如下:
給一個知乎上大神的回答作爲參考,寫得很棒很清晰:Lambda 表達式有何用處?如何使用?
python 的 GUI 編程
2016.09.26 更新
早上看到這篇文章:Python 的圖形界面(GUI)編程?,講了幾個 python 中可實現 GUI 編程的幾個框架:
- PyQt
- wxPython
- Tkinter模塊
- PySide
查看 h5py 文件
2016.10.06 更新
import h5py
db = h5py.File('.../results/SynthText.h5', 'r')
dsest = db.keys()
print dsets
輸出爲:
這樣就能查看 h5
文件中的 keys 了。
用 OS 模塊新建 txt 文件
2016.10.12 更新
import os
#新建 txt 文件
os.mknod("***.txt")
用 pip 升級 python 模塊
2016.10.21 更新
如要升級 Cython
模塊,從 0.20 版本升級到最新的版本:
sudo pip install cpthon --upgrade
s升級完成後:
中文字符編碼與轉換問題
2016.11.03 更新
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# tankywoo@2013-02-24
name = '你好'
s = u'你們'
print s + unicode(name, 'utf-8')
print s + name.decode('utf-8')
print s.encode('utf-8') + name
print type(name)
print type(s)
print type(name.decode('utf-8'))
print type(s.encode('utf-8'))
輸出結果:
在循環中獲取索引(數組下標)
2016.11.04 更新
ints = [8, 23, 45, 12, 78]
,當我循環這個列表時如何獲得它的索引下標?
如果像C或者PHP那樣加入一個狀態變量那就太不pythonic了.
最好的選擇就是用內建函數 enumerate:
for idx, val in enumerate(ints):
print idx, val