- print兩種寫法
- 打印pytorch權重
- python os.path glob
- np.unique(b) numpy 去重
- 根據標簽圖和顏色表顯示標簽圖
- pytorch繼承的Dataset類的自己定義的OrientClassifyDataset,可以用iter next來迭代訪問
- to_tensor || transforms.functional.to_tensor
- pytorch數據處理,繼承的Dataset類的函數的單元測試
- pytorch保存模型兩種方式
- shape[1,6] + shape[6,1] = shape[6,6]
- numpy 數組,[x1,y1,x2,y2,score,cls] 比如我有形狀[100,6]這樣的一個numpy數組,需要保留score大於0.8的,其余不要。如何寫?
- 圖片保持長寬比,縮放到固定尺寸
- python 時間統計
- c++ 時間統計
- c++ 寫入文本
- PIL 顯示圖片並等待
- lstm crnn 圖片歸一化定長
- 圖像按照高度切分
print兩種寫法
print('[Epoch: %d, numImages: %5d]' % (epoch, i * self.args.batch_size + image.data.shape[0]))
print("Acc:{}, Acc_class:{}, mIoU:{}, fwIoU: {}".format(Acc, Acc_class, mIoU, FWIoU))
print('Loss: %.3f' % test_loss)
print(f'The corresponding prune ratio is {percent_limit:.3f}.')
打印pytorch權重
model = model.cuda()
print("Model's state_dict:")
for param_tensor in model.state_dict():
print(param_tensor, "\t", model.state_dict()[param_tensor].size())
print(model.state_dict()['backbone.layer1.0.conv1.weight'][0])
打印如下:
Model's state_dict:
backbone.conv1.weight torch.Size([64, 3, 7, 7])
backbone.bn1.weight torch.Size([64])
backbone.bn1.bias torch.Size([64])
backbone.bn1.running_mean torch.Size([64])
backbone.bn1.running_var torch.Size([64])
backbone.bn1.num_batches_tracked torch.Size([])
backbone.layer1.0.conv1.weight torch.Size([64, 64, 1, 1])
backbone.layer1.0.bn1.weight torch.Size([64])
backbone.layer1.0.bn1.bias torch.Size([64])
backbone.layer1.0.bn1.running_mean torch.Size([64])
backbone.layer1.0.bn1.running_var torch.Size([64])
backbone.layer1.0.bn1.num_batches_tracked torch.Size([])
backbone.layer1.0.conv2.weight torch.Size([64, 64, 3, 3])
backbone.layer1.0.bn2.weight torch.Size([64])
backbone.layer1.0.bn2.bias torch.Size([64])
backbone.layer1.0.bn2.running_mean torch.Size([64])
backbone.layer1.0.bn2.running_var torch.Size([64])
backbone.layer1.0.bn2.num_batches_tracked torch.Size([])
backbone.layer1.0.conv3.weight torch.Size([256, 64, 1, 1])
backbone.layer1.0.bn3.weight torch.Size([256])
backbone.layer1.0.bn3.bias torch.Size([256])
backbone.layer1.0.bn3.running_mean torch.Size([256])
backbone.layer1.0.bn3.running_var torch.Size([256])
backbone.layer1.0.bn3.num_batches_tracked torch.Size([])
backbone.layer1.0.downsample.0.weight torch.Size([256, 64, 1, 1])
backbone.layer1.0.downsample.1.weight torch.Size([256])
backbone.layer1.0.downsample.1.bias torch.Size([256])
backbone.layer1.0.downsample.1.running_mean torch.Size([256])
backbone.layer1.0.downsample.1.running_var torch.Size([256])
backbone.layer1.0.downsample.1.num_batches_tracked torch.Size([])
backbone.layer1.1.conv1.weight torch.Size([64, 256, 1, 1])
backbone.layer1.1.bn1.weight torch.Size([64])
backbone.layer1.1.bn1.bias torch.Size([64])
backbone.layer1.1.bn1.running_mean torch.Size([64])
...
tensor([[[-1.8738e-01]],
[[ 2.3853e-02]],
[[-2.1837e-02]],
[[-5.4712e-02]],
[[ 2.1917e-02]],
[[ 1.4151e-09]],
[[ 8.2899e-02]],
[[-1.8761e-08]],
[[-1.2909e-08]],
...
[[ 5.3678e-02]],
[[-1.3887e-08]],
[[-5.2007e-02]]], device='cuda:0')
model.load_state_dict(checkpoint['state_dict'],strict=False)
strict=False表示名字對不上的就不加載,
默認是true,如果有名字不一致就報錯
python os.path glob
directory = os.path.join(path_tmp, 'tmp', 'pascal')
aa = glob.glob(os.path.join(directory, 'experiment_*'))
print(directory)
# /data_2/everyday/0815/tmp/pascal
print(aa)
# ['/data_2/everyday/0815/tmp/pascal/experiment_7', '/data_2/everyday/0815/tmp/pascal/experiment_0', '/data_2/everyday/0815/tmp/pascal/experiment_1']
bb = sorted(glob.glob(os.path.join(directory, 'experiment_*')))
print(bb)
# ['/data_2/everyday/0815/tmp/pascal/experiment_0', '/data_2/everyday/0815/tmp/pascal/experiment_1', '/data_2/everyday/0815/tmp/pascal/experiment_7']
id = 7
experiment_dir = os.path.join(directory, 'experiment_{}'.format(str(id)))
print(experiment_dir)
# /data_2/everyday/0815/tmp/pascal/experiment_7
這里'experiment_{}'.format(str(id) 寫法可以代替字符串
2.提取文件名
path = '/data_2/fengjing'
file_name = os.path.basename(path)
np.unique(b) numpy 去重
import numpy as np
b = np.array([(1.5, 2, 3), (3, 5, 6),(1,2,3),(4,5,6)])
print(b)
print(b.shape)
a = np.unique(b)
print(a)
打印如下:
[[1.5 2. 3. ]
[3. 5. 6. ]
[1. 2. 3. ]
[4. 5. 6. ]]
(4, 3)
[1. 1.5 2. 3. 4. 5. 6. ]
這個可以用在:比如訓練分割的時候數據檢查。
例如:
標簽圖有16萬,分割的標簽圖看起來都是黑的,里面的像素值代表類別,
說好的只有26個類別,但是訓練的時候莫名其妙的報錯,報cudnn的錯誤:
THCudaCheck FAIL file=/opt/conda/conda-bld/pytorch_1532581333611/work/aten/src/THC/THCCachingHostAllocator.cpp line=271 error=59 : device-side assert triggered
Traceback (most recent call last):
File "/data_2/tmp_paper/image-segmentation/DeepLab/v3+/pytorch0.41/pytorch-deeplab-xception-master/train.py", line 339, in <module>
main()
File "/data_2/tmp_paper/image-segmentation/DeepLab/v3+/pytorch0.41/pytorch-deeplab-xception-master/train.py", line 298, in main
trainer.training(epoch)
File "/data_2/tmp_paper/image-segmentation/DeepLab/v3+/pytorch0.41/pytorch-deeplab-xception-master/train.py", line 108, in training
loss.backward()
File "/data_1/Yang/software_install/Anaconda1105/envs/pytorch0.4.1/lib/python3.6/site-packages/torch/tensor.py", line 93, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph)
File "/data_1/Yang/software_install/Anaconda1105/envs/pytorch0.4.1/lib/python3.6/site-packages/torch/autograd/__init__.py", line 90, in backward
allow_unreachable=True) # allow_unreachable flag
RuntimeError: CuDNN error: CUDNN_STATUS_EXECUTION_FAILED
搜cudnn的,都是亂七八糟的,沒有可用的。
但是仔細看上面還有一個提示:
line=271 error=59 : device-side assert triggered
這句話百度,有人解答說是標簽超過類別數了。
於是我就開始懷疑我的16萬數據里面是不是有超過類別數的標簽,分割的標簽圖看起來都是黑的,里面的像素值代表類別,我是26類,那么標簽范圍是0-25,所以
我就用上了np.unique這個函數,檢查數據的代碼如下:
import os
from PIL import Image
import numpy as np
txt_list = '/data_2/2019biaozhushuju/seg-chewaiguan/seg_chewaigaun_ding/se_chewaiguan_data/20190618_new/train.txt'
with open(txt_list,'r')as fr:
lines = fr.readlines()
for line in lines:
line = line.strip().split(' ')
_target = Image.open(line[1]).convert('L')
# _target.show()
targe = np.array(_target)
a = np.unique(targe)
max_val = max(a)
if max_val >= 26:
print (max_val, "::", line[1])
!!!果真,有打印!!!原來真有幾張圖片超過標簽,坑爹啊,這個錯誤排查了2-3個小時!!!
根據標簽圖和顏色表顯示標簽圖
import numpy as np
import cv2
import os
from PIL import Image
mmm = cv2.imread("/data_2/fengjing.jpg")
cv2.imshow("m",mmm)
cv2.waitKey(0)
#BGR
color_segmentation=np.asarray([
[0,0,0], #[0]背景
[180,120,120],
[6,230,230],
[80,50,50],
[4,200,3],
[120,120,80],
[140,140,140],
[204,5,255],
[230,230,230],
[4,250,7],
[40,150,255],
[235,255,7],
[150,5,61],
[120,120,70],
[8,255,51],
[255,6,82],
[143,255,140],
[204,255,4],
[255,51,7],
[204,70,3],
[0,102,200],
[61,230,250],
[255,6,51],
[11,102,255],
[255,7,71],
[255,9,224],
[9,7,230],
[220,220,220],
[255, 9, 92]
],dtype=np.uint8)
def decode_segmap(label_mask,n_classes = 21):
r = label_mask.copy()
g = label_mask.copy()
b = label_mask.copy()
for ll in range(0, n_classes):
# aaa = color_segmentation[ll, 1]
# position = label_mask == ll
b[label_mask == ll] = color_segmentation[ll, 0]
g[label_mask == ll] = color_segmentation[ll, 1]
r[label_mask == ll] = color_segmentation[ll, 2]
rgb = np.zeros((label_mask.shape[0], label_mask.shape[1], 3))
print(rgb[240][240])
rgb[:, :, 0] = b
rgb[:, :, 1] = g
rgb[:, :, 2] = r
# rgb[:, :, 0] = b / 255.0
# rgb[:, :, 1] = g / 255.0
# rgb[:, :, 2] = r /255.0
rgb = rgb.astype(np.uint8) ##重要! 要不然opencv顯示有問題
print(rgb[240][240])
return rgb
root_dir = "/data_2/2019biaozhushuju/others/voc/VOCdevkit/VOC2012/SegmentationClassAug/"
list_gray_img = os.listdir(root_dir)
for img_name in list_gray_img:
path_gray = root_dir + img_name
laber_mask = cv2.imread(path_gray,0) ##灰度 單通道讀取
# print(laber_mask.shape)
color_img = decode_segmap(laber_mask)
# print(color_img.shape)
# img1 = Image.fromarray(color_img.astype('uint8')).convert('RGB')
# img1.show()
cv2.imshow("laber_mask", laber_mask*20)
cv2.imshow("color",color_img)
cv2.waitKey()
這里直接放的正確的代碼,一開始顯示的圖片有問題啊,沒有顏色
找問題找了半天
aaa = color_segmentation[ll, 1]
print(rgb[240][240])
上面這個在代碼里面打印出來的像素值是正常的,都是比如我上面的顏色表里面的,既然像素正常那顯示為啥沒有顏色呢?難道是我opencv出問題了嗎。然后可以看開頭我直接讀取一張圖片顯示,是可以正常顯示的,然后我加PIL庫來顯示,
img1 = Image.fromarray(color_img.astype('uint8')).convert('RGB')
顯示出來的圖像是彩色的,那為啥opencv顯示有問題呢,然后我rgb[:, :, 0] = b / 255.0,然后發現opencv顯示就正常了,好奇怪啊,/255就變為0-1之間了啊。。。反正很奇怪,找了很久,然后突然想到可以是數據格式的問題!果斷打斷點:
發現我加載的那張圖片格式是:dtype=uint8格式的,而color這個圖格式是float64格式的!所以問題就出現在這里!!
一定要加上這句話
rgb = rgb.astype(np.uint8) ##重要! 要不然opencv顯示有問題
好了,只是把我發現問題,解決問題的思路過程寫在這里。
這里主要要學習numpy的幾個操作:
1.
r = label_mask.copy()
g = label_mask.copy()
b = label_mask.copy()
for ll in range(0, n_classes):
b[label_mask == ll] = color_segmentation[ll, 0]
g[label_mask == ll] = color_segmentation[ll, 1]
r[label_mask == ll] = color_segmentation[ll, 2]
這里我一開始的直觀理解就是label_mask == ll返回的是位置,b[label_mask == ll],比如圖片像素值等於2的位置都填充后面的值。但是我
position = label_mask == ll
看了一下,其實不是,這里的position是和圖一樣大小,里面的值都是True或者False
明白了,其實返回的相當於一個mask,只在true的位置上填充后面的值
2.
rgb = np.zeros((label_mask.shape[0], label_mask.shape[1], 3))
rgb[:, :, 0] = b
rgb[:, :, 1] = g
rgb[:, :, 2] = r
這里rgb都是單通道的,就是把這三個合並一個圖。首先就是申請了一個三通的。這里需要注意的是opencv的格式都是hwc。
rgb[:, :, 0]代表的第一個通道
還有上面我調試的代碼
print(rgb[240][240])
這里打印出來的是這樣的
[80. 50. 50.]
想想為啥吧!
@@@@@@@@@@
有個相反操作的,就是把colormap圖映射為標簽圖
def encode_segmap(mask):
"""Encode segmentation label images as pascal classes
Args:
mask (np.ndarray): raw segmentation label image of dimension
(M, N, 3), in which the Pascal classes are encoded as colours.
Returns:
(np.ndarray): class map with dimensions (M,N), where the value at
a given location is the integer denoting the class index.
"""
mask = mask.astype(int)
label_mask = np.zeros((mask.shape[0], mask.shape[1]), dtype=np.int16)
for ii, label in enumerate(get_pascal_labels()):
label_mask[np.where(np.all(mask == label, axis=-1))[:2]] = ii
label_mask = label_mask.astype(int)
return label_mask
pytorch繼承的Dataset類的自己定義的OrientClassifyDataset,可以用iter next來迭代訪問
train_dataset = OrientClassifyDataset(
train_root,
transform=train_transform,
)
aa = iter(train_dataset)
a = next(aa)
print('train data:', len(train_dataset))
train_loader = data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True,
num_workers=num_workers, drop_last=True, collate_fn=align_collate_train)
to_tensor || transforms.functional.to_tensor
將numpy數組或PIL.Image讀的圖片轉換成(C,H, W)的Tensor格式且/255歸一化到[0,1.0]之間
import torchvision.transforms as transforms
class Normalize(object):
def __init__(self):
pass
def __call__(self, img):
img = transforms.functional.to_tensor(img)
img.sub_(0.5).div_(0.5)
return img
pytorch數據處理,繼承的Dataset類的函數的單元測試
反向操作,之前減均值,除方差操作現在反着來恢復原圖變顯示
本文大部分代碼參考這個倉庫:https://github.com/jfzhang95/pytorch-deeplab-xception
voc_train = VOCSegmentation(args, split='train')
dataloader = DataLoader(voc_train, batch_size=5, shuffle=True, num_workers=0)
for ii, sample in enumerate(dataloader):
for jj in range(sample["image"].size()[0]):
img = sample['image'].numpy()
gt = sample['label'].numpy()
tmp = np.array(gt[jj]).astype(np.uint8)
segmap = decode_segmap(tmp, dataset='pascal')
img_tmp = np.transpose(img[jj], axes=[1, 2, 0])
img_tmp *= (0.229, 0.224, 0.225)
img_tmp += (0.485, 0.456, 0.406)
img_tmp *= 255.0
img_tmp = img_tmp.astype(np.uint8)
plt.figure()
plt.title('display')
plt.subplot(211)
plt.imshow(img_tmp)
plt.subplot(212)
plt.imshow(segmap)
if ii == 1:
break
plt.show(block=True)
pytorch保存模型兩種方式
保存和加載模型參數有兩種方式:
方式一:
torch.save(net.state_dict(),path):
功能:保存訓練完的網絡的各層參數(即weights和bias)
其中:net.state_dict()獲取各層參數,path是文件存放路徑(通常保存文件格式為.pt或.pth)
net2.load_state_dict(torch.load(path)):
功能:加載保存到path中的各層參數到神經網絡
注意:不可以直接為torch.load_state_dict(path),此函數不能直接接收字符串類型參數
方式二:
torch.save(net,path):
功能:保存訓練完的整個網絡模型(不止weights和bias)
net2=torch.load(path):
功能:加載保存到path中的整個神經網絡
說明:官方推薦方式一,原因自然是保存的內容少,速度會更快。
shape[1,6] + shape[6,1] = shape[6,6]
>>> a = np.array([[3,2,1,1,2,3]])
>>> b = np.array([[3],[2],[1],[1],[2],[3]])
>>> print(a.shape),print(b.shape)
(1, 6)
(6, 1)
(None, None)
>>> c = a+b
>>> print(a)
[[3 2 1 1 2 3]]
>>> print(b)
[[3]
[2]
[1]
[1]
[2]
[3]]
>>> print(c)
[[6 5 4 4 5 6]
[5 4 3 3 4 5]
[4 3 2 2 3 4]
[4 3 2 2 3 4]
[5 4 3 3 4 5]
[6 5 4 4 5 6]]
numpy 數組,[x1,y1,x2,y2,score,cls] 比如我有形狀[100,6]這樣的一個numpy數組,需要保留score大於0.8的,其余不要。如何寫?
問群里人,得到三種答案:
import numpy as np
a = [[1, 2, 3, 4, 0.75, 1],
[1, 2, 3, 4, 0.85, 2],
[1, 2, 3, 4, 0.95, 3],
[1, 2, 3, 4, 0.61, 4],
[1, 2, 3, 4, 0.97, 5],
[1, 2, 3, 4, 0.82, 6],]
a = np.array(a)
####11111
s = a[np.apply_along_axis(lambda x:x[4]>0.8,axis=1,arr=a)]
print(s)
print()
####2222
mask = a[:,4] > 0.8
print(mask)
print(a[mask])
print()
####333
print(a[a[:,4]>0.8,:])
#######################################
[[1. 2. 3. 4. 0.85 2. ]
[1. 2. 3. 4. 0.95 3. ]
[1. 2. 3. 4. 0.97 5. ]
[1. 2. 3. 4. 0.82 6. ]]
[False True True False True True]
[[1. 2. 3. 4. 0.85 2. ]
[1. 2. 3. 4. 0.95 3. ]
[1. 2. 3. 4. 0.97 5. ]
[1. 2. 3. 4. 0.82 6. ]]
[[1. 2. 3. 4. 0.85 2. ]
[1. 2. 3. 4. 0.95 3. ]
[1. 2. 3. 4. 0.97 5. ]
[1. 2. 3. 4. 0.82 6. ]]
Process finished with exit code 0
圖片保持長寬比,縮放到固定尺寸
int input_w = 512;
int input_h = 512;
float scale = cv::min(float(input_w)/img.cols,float(input_h)/img.rows);
auto scaleSize = cv::Size(img.cols * scale,img.rows * scale);
cv::Mat resized;
cv::resize(img, resized,scaleSize,0,0);
cv::Mat cropped = cv::Mat::zeros(input_h,input_w,CV_8UC3);
cv::Rect rect((input_w- scaleSize.width)/2, (input_h-scaleSize.height)/2, scaleSize.width,scaleSize.height);
resized.copyTo(cropped(rect));
python 時間統計
import time
start = time.time()
cnt_file = 0
for path, img, im0s, vid_cap in dataset:
cnt_file += 1
## do somethings
torch.cuda.synchronize()
end = time.time()
time_1 = end - start
print("all time=", time_1 * 1000.0)
print("ave time=", time_1 * 1000.0 / (cnt_file))
print("all file=", cnt_file)
c++ 時間統計
#include <torch/script.h>
#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
#include <memory>
#include <stdio.h>
#include <sys/time.h>
#include<cuda_runtime.h>
std::fstream infile("/data_1/2020biaozhushuju/2020_detection/small/test_data/list.txt");
std::string path_img;
int cnt = 0;
auto t_0 = std::chrono::steady_clock::now();
while(infile >> path_img)
{
std::cout<<++cnt << "::"<<path_img<<std::endl;
//to do somethings
}
cudaDeviceSynchronize();
auto ttt = std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::steady_clock::now() - t_0).count();
std::cout << "ave consume time="<<ttt*1.0/cnt <<"ms"<<std::endl;
c++ 寫入文本
std::ofstream outfile(path);
for(int i=0;i<result_data.size(0);i++)
{
float score = result_data[i][4];
if(score < opt.conf_thresh) { continue;}
float x1 = result_data[i][0];
float y1 = result_data[i][1];
float x2 = result_data[i][2];
float y2 = result_data[i][3];
affine_transform(x1, y1, trans, x1, y1);
affine_transform(x2, y2, trans, x2, y2);
int id_label = result_data[i][5];
std::string line = label_map_small[id_label] + (std::string)" " + std::to_string(score) + (std::string)" " +\
(std::string)std::to_string((int)x1) + (std::string)" " \
+ (std::string)std::to_string((int)y1) + (std::string)" " \
+ (std::string)std::to_string((int)x2) + (std::string)" " \
+ (std::string)std::to_string((int)y2) + (std::string)" ";
if(i != (result_data.size(0)-1))
{
line += (std::string)("\n");
}
outfile << line;
}
outfile.close();
PIL 顯示圖片並等待
from PIL import Image
import matplotlib.pyplot as plt
list_img = os.listdir(dir_img)
for cnt,img_name in enumerate(list_img):
print(cnt,img_name)
path_img = dir_img + img_name
image_show = Image.open(path_img)
# image_show.show() ##這里用這句會把圖像全部顯示出來
plt.figure("dog")
plt.imshow(image_show)
plt.show()
lstm crnn 圖片歸一化定長
def LstmCrnnStandard(img, ratio, stand_w, stand_h):
img_h, img_w, _ = img.shape
if img_h<2 or img_w<2:
return
ratio_now = img_w * 1.0 / img_h
if ratio_now <= ratio:
mask = np.ones((img_h, int(img_h * ratio), 3), dtype=np.uint8) * 255
mask[0:img_h,0:img_w,:] = img
else:
mask = np.ones((int(img_w*1.0/ratio), img_w, 3), dtype=np.uint8) * 255
mask[0:img_h, 0:img_w, :] = img
mask_stand = cv2.resize(mask,(stand_w, stand_h),interpolation=cv2.INTER_AREA)
return mask_stand
圖像按照高度切分
import cv2
path = "/data_2/123.jpg"
img = cv2.imread(path)
h,w,c = img.shape
top = img[0:int(h/2),:,:]
down = img[int(h/2):h,:,:]
cv2.imshow("img",img)
cv2.imshow("top",top)
cv2.imshow("down",down)
cv2.waitKey(0)
a = 0