日常筆記:Python(1)

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')

這樣就完成了,我用的是 shutilshutil.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 更新

來源:Python普通字符串和Unicode相加問題?

#!/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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章