2019年4月11日星期四

Failed to find TIFF library

ImportError: Failed to find TIFF library. Make sure that libtiff is installed and its location is listed in PATH|LD_LIBRARY_PATH|..

解决方法:
I have actually experienced the same problem as elktoe when I tried to install libtiff on my current Mac workstation, this can be solved perfectly with mac compiled libtiff with brew. Make sure you get rid of the previous not working libtiff module before you install mac compiled libtiff
pip3 uninstall libtiff
then
brew install libtiff as suggested by @lsqshr, see if it works.

2019年1月31日星期四

Cannot import name relu6


Just execute these commands:
git clone https://github.com/apple/coremltools.git
cd coremltools
cmake . -DPYTHON=$(which python) -DPYTHON_CONFIG=$(which python-config)
make
pip install -e .

2019年1月29日星期二

FPN网络训练报错PaddingFIFOQueue '_1_get_batch/batch/padding_fifo_queue' is closed and has insufficient elements (requested 1, current size 0)


https://github.com/DetectionTeamUCAS/FPN_Tensorflow
按说明设置自己的训练集后,进入tool/运行train.py后报错:

PaddingFIFOQueue '_1_get_batch/batch/padding_fifo_queue' is closed and has insufficient elements (requested 1, current size 0)

查了一下,应该是xml文件中box坐标范围导致的。修改data/io/convert_data/io/convert_to_tfrecord.py中line68为

  gtbox_label = np.array(box_list, dtype=np.int32)  # [x1, y1. x2, y2, label]

  xmin, ymin, xmax, ymax, label = gtbox_label[:, 0], gtbox_label[:, 1], gtbox_label[:, 2],\
      gtbox_label[:, 3], gtbox_label[:, 4]

  xmin = np.where(xmin <= 0, 1, xmin)
  ymin = np.where(ymin <= 0, 1, ymin)
  xmax = np.where(xmax >= img_width, img_width-1, xmax)
  ymax = np.where(ymax >= img_height, img_height-1, ymax)

  # [ymin, xmin, ymax, xmax, label]
  gtbox_label = np.transpose(np.stack([ymin, xmin, ymax, xmax, label], axis=0))

即可。












2019年1月16日星期三

TypeError: ...has type str, but expected one of: bytes

在python3环境中将数据转为TFRecord时遇到的问题
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
TypeError: 'rock' has type str, but expected one of: bytes

解决方式:
转byte feature时用tf.compat.as_bytes(value)将字节或 Unicode 转换为 bytes,使用 UTF-8 编码文本:
def _bytes_feature(value):
  value = tf.compat.as_bytes(value)#####
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))

2019年1月9日星期三

pip2与pip3共存

之前修改了导致pip2无法使用,导致一些开发工具无法使用。 可以先解除 python3的软连接, 然后再修改成 python2的. mac 自带的是 python2.7
1. 先获取2.7的路径:
which python2.7, 我的是/usr/bin/python2.7
2. 解除原有链接 unlink /usr/bin/python
3. 恢复默认链接: sudo ln -s python2 /usr/bin/python

2018年12月24日星期一

行人重识别

项目地址:
https://github.com/huanghoujing/person-reid-triplet-loss-baseline#visualize-ranking-list
test命令:

python2 script/experiment/train.py -d '(0,)' --only_test true --dataset duke --last_conv_stride 1 --normalize_feature false --exp_dir exp --model_weight_file /home/zhoujie/person-reid-triplet-loss-baseline/model_weight/duke_stride1/model_weight.pth


项目地址:
https://github.com/layumi/Person_reID_baseline_pytorch/tree/master/tutorial
train命令:

python train.py --gpu_ids 0 --name ft_ResNet50 --train_all --batchsize 32  --data_dir /home/zhoujie/Person_reID_baseline_pytorch


2018年12月5日星期三

coco数据集转换pascal VOC数据集

1)得到annotations/json格式:labelme2coco.py

输入: 
 # 把所有的jpg和json都放到了images目录下
    base_dir = '/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/image'

输出:
 # 把训练集转化为COCO的json格式
    l2c_train = Lableme2CoCo()
    train_instance = l2c_train.to_coco(train_path)
    l2c_train.save_coco_json(train_instance, '/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/annotations/instances_train2017.json')

    # 把验证集转化为COCO的json格式
    l2c_val = Lableme2CoCo()
    val_instance = l2c_val.to_coco(val_path)
    l2c_val.save_coco_json(val_instance, '/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/annotations/instances_val2017.json')


2)得到根目录下单个json文件:getclassnum.py

输入:cocojson="/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/annotations/instances_train2017.json"

输出:
COCO_train.json


3)得到VOC xml标注文件:createXML.py

输入:
_IMAGE_PATH = '/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/imageonly/'

with open("COCO_train.json", "r") as f:
        ann_data = json.load(f)

输出:
_ANNOTATION_SAVE_PATH = '/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/data/VOC2018/Annotations'

4)生成ImageSets/Main/text文件:darknet/traintxt.py

输入:
xmlfilepath = '/Users/sisyphus/tf-faster-rcnn/data/VOCdevkit2007/VOC2007/Annotations'

输出:
saveBasePath = "/Users/sisyphus/tf-faster-rcnn/data/VOCdevkit2007/VOC2007/"

ftrainval = open(os.path.join(saveBasePath,'ImageSets/Main/trainval.txt'), 'w') 
ftest = open(os.path.join(saveBasePath,'ImageSets/Main/test.txt'), 'w') 
ftrain = open(os.path.join(saveBasePath,'ImageSets/Main/train.txt'), 'w') 
fval = open(os.path.join(saveBasePath,'ImageSets/Main/val.txt'), 'w') 


PS:
数据增强:
/Users/sisyphus/TIANCHI_XUELANG_AI_gangban/src/DataAugForTrainAndTest_DET.py

重命名jpg或xml名称:
mAP/changeTextName.py

修改xml中对应图片名称:
py/xmlEdit2.py










2018年11月27日星期二

tf faster rcnn推导测试集计算mAP报错

训练完毕后运行./experiments/scripts/test_faster_rcnn.sh 0 pascal_voc res101
测试mAP,报错:
and the problem:
VOC07 metric? Yes
000001
Traceback (most recent call last):
File "./tools/test_net.py", line 90, in
test_net(net, imdb, max_per_image=args.max_per_image, vis=args.vis)
File "/home/rs/myGithub/py-faster-rcnn/tools/../lib/fast_rcnn/test.py", line 295, in test_net
imdb.evaluate_detections(all_boxes, output_dir)
File "/home/rs/myGithub/py-faster-rcnn/tools/../lib/datasets/pascal_voc.py", line 322, in evaluate_detections
self._do_python_eval(output_dir)
File "/home/rs/myGithub/py-faster-rcnn/tools/../lib/datasets/pascal_voc.py", line 285, in _do_python_eval
use_07_metric=use_07_metric)
File "/home/rs/myGithub/py-faster-rcnn/tools/../lib/datasets/voc_eval.py", line 127, in voc_eval
R = [obj for obj in recs[imagename] if obj['name'] == classname]
KeyError: '000001'
解决方法:
had the same problem with an old annotation cache. Just delete it
rm data/VOCdevkit2007/annotations_cache/annots.pkl and run the program again.
You should also delete the roidb cache:
rm data/cache/voc_2007_trainval_gt_roidb.pkl


PS:如要可视化测试结果,可在CPU电脑上运行tf-faster-rcnn/tools/demo_one.py程序。






2018年11月22日星期四

tf faster rcnn 训练自己的数据集


1 按照https://github.com/endernewton/tf-faster-rcnn中介绍步骤安装项目。

2 用自己的数据集替换VOC2007数据集文件夹。

3 修改lib/datasets/pascal_voc.py中

self._classes = ('__background__',  # always index 0       "defect0","defect1","defect2","defect3","defect4","defect5","defect6","defect7","defect8","defect9")####################
 
4 lib/datasets/factory.py和experiments/scripts/train_faster_rcnn, experiments/scripts/test_faster_rcnn中,因为自己数据集名称和VOC2007一致,暂不用修改。

5 开始训练

./experiments/scripts/train_faster_rcnn.sh 0 pascal_voc res101
注意每次训练前删除output和data/cache文件夹。

训练时其它可能需要修改的参数:
1)修改迭代次数:experiments/scripts/train_faster_rcnn.sh文件中修改迭代次数
experiments/scripts/test_faster_rcnn.sh中也相应修改
2) 学习率设置:tf-faster-rcnn/lib/model/config.py文件中设置



6 tools/demo.py修改种类数
net.create_architecture("TEST", 11,#####################21


可能出现的错误:
1)InvalidArgumentError (see above for traceback): Nan in summary histogram for: 


it's because in the file 'pascal_voc.py', the function '_load_pascal_annotation' has an operation of make pixel indexes 0-based,the code is :
x1 = float(bbox.find('xmin').text) - 1
y1 = float(bbox.find('ymin').text) - 1
x2 = float(bbox.find('xmax').text) - 1
y2 = float(bbox.find('ymax').text) - 1
删除-1

2)assert(cfg.TRAIN.BATCH_SIZE % num_images == 0), 
ZeroDivisionError: integer division or modulo by zero

test.txt不能为空







2018年11月20日星期二

xml和json无法显示中文

解决办法:在相关语句中添加“encoding='utf-8'”。
如:

xmldoc.write(xmlpath+xmllist[i], encoding='utf-8')

json.dump(instance, open(save_path, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)

with open(path, "r", encoding='utf-8') as f:

2018年11月19日星期一

ImportError: No module named Cython.Distutils

Ubuntu下使用tensorflow版faster-RCNN执行make命令报错

For python3 use
sudo apt-get install cython3
For python2 use
sudo apt-get install cython

2018年11月6日星期二

安装OpenCV3.4.2

from: https://cloud.tencent.com/developer/article/1329166

安装OpenCV3.4.2
注意:想要在OpenCV中玩转YOLOv3,必须安装OpenCV3.4.2版本及以上。
Python版安装方法
1# 推荐安装外挂版
2pip install opencv-contrib-python
3
4# 或者安装正常版
5pip install opencv-python

2018年10月18日星期四

Ubuntu使用darknet遇到的坑

修改makefile文件
GPU=1
CUDNN=1
NVCC=/usr/local/cuda-9.0/bin/nvcc #即改为本机CUDA安装地址
make后报错
include/darknet.h:16:23: fatal error: cudnn.h: 没有那个文件或目录
compilation terminated.
Makefile:89: recipe for target 'obj/gemm.o' failed
make: *** [obj/gemm.o] Error 1

是因为缺乏头文件cudnn.h
执行
cd /home/zhoujie/.conda/envs/tf/include
sudo cp cudnn.h /usr/include

再次make后报错
/usr/bin/ld: 找不到 -lcudnn
collect2: error: ld returned 1 exit status
Makefile:83: recipe for target 'libdarknet.so' failed
make: *** [libdarknet.so] Error 1

这是因为缺少库文件libcudnn.so
执行
cd /home/zhoujie/.conda/envs/tf/lib
sudo cp libcudnn.so /usr/local/cuda/lib64

make成功

执行推导图片命令后报错

libcudart.so.8.0: cannot open shared object file: No such file or directory


执行
sudo ldconfig /usr/local/cuda/lib64

就可以正常推导和训练
















2018年9月17日星期一

darkflow目标检测


cd darkflow
python flow --model cfg/yolo.cfg --load bin/yolo.weights --demo MOT16-13.mp4

2018年8月30日星期四

Faster RCNN_tensorflow训练自己的数据集


按主页修改后,

转化为tfrecoard:
python convert_data_to_tfrecord.py --VOC_dir='/home/zhoujie/Faster-RCNN_Tensorflow/VOCdevkit/VOCdevkit_train/' --xml_dir='Annotation' --image_dir='JPEGImages' --save_name='train' --img_format='.jpg' --dataset='pascal' --save_dir='/home/zhoujie/Faster-RCNN_Tensorflow/data/tfrecord/'
训练:

cd $PATH_ROOT/tools
python train.py

2018年8月14日星期二

远程查看tensorboard


Step1 : ssh -L 16006:127.0.0.1:6006 zhoujie@10.140.92.35 
Step2: tensorboard --logdir="/home/zhoujie/keras-retinanet/logs"
Step3: 在本地主机访问 http://127.0.0.1:16006/


2018年8月1日星期三

keras传入数据报错

TypeError: unsupported operand type(s) for /=: 'JpegImageFile' and 'float'

修改方法:
from keras.applications import xception
from keras.preprocessing import image


def preprocess_input_new(x):
    img = xception.preprocess_input(image.img_to_array(x))
    return image.array_to_img(img)

ImageDataGenerator(
      preprocessing_function=preprocess_input_new,
      rotation_range=30,
      width_shift_range=0.2,
      height_shift_range=0.2,
      shear_range=0.2,
      zoom_range=0.2,
      horizontal_flip=True
  )

2018年7月6日星期五

YOLO3数据集准备

1 修改jpg和xml名字:
#先改jpg名,再改xml名,类似DW001.jpg,DW002.xml。。
#

 
import os 
 
class BatchRename(): 
    '''''
    批量重命名文件夹中的图片文件

    ''' 
    def __init__(self): 
        #我的图片文件夹路径horse 
        self.path = '/Users/sisyphus/TianChi/traindata/normalxml'
 
    def rename(self): 
        filelist = os.listdir(self.path)
        #filelist.sort()#+
        filelist.sort(key=lambda x:int(x[-6:-4]))#以**.jpg排序
        total_num = len(filelist) 
        i = 1 
        n = 6 
        for item in filelist: 
#            if item.endswith('.jpg'): ##################
            if item.endswith('.xml'):
                print(item)
                n = 3 - len(str(i)) 
                src = os.path.join(os.path.abspath(self.path), item) 
#                dst = os.path.join(os.path.abspath(self.path), str('normal')+str(0)*n + str(i) + '.jpg')############
                dst = os.path.join(os.path.abspath(self.path), str('normal')+str(0)*n + str(i) + '.xml')
                try: 
                    os.rename(src, dst) 
                    print('converting %s to %s ...' % (src, dst))
                    i = i + 1 
             
                except: 
                    continue 
        print('total %d to rename & converted %d jpgs/xml' % (total_num, i-1)) 
 
if __name__ == '__main__': 
    demo = BatchRename() 
    demo.rename()


2. 修改xml内容:
from xml.etree import ElementTree
import os

jpgpath="/Users/sisyphus/TianChi/traindata/normal/"#末尾要加斜杠
jpglist = os.listdir(jpgpath)
jpglist.sort()


xmlpath="/Users/sisyphus/TianChi/traindata/normalxml/"########
xmllist = os.listdir(xmlpath)
xmllist.sort()

i=0
for item in xmllist:
#    print(item)
    xmldoc = ElementTree.parse(xmlpath+xmllist[i])
    node = xmldoc.find('./filename')
    node.text = jpglist[i]
    node = xmldoc.find('object/name')
    node.text = 'normal'    #######################
    ##以下针对normal
    node = xmldoc.find('object/bndbox/xmin')
    node.text = '0'
    node = xmldoc.find('object/bndbox/ymin')
    node.text = '0'
    node = xmldoc.find('object/bndbox/xmax')
    node.text = '0'
    node = xmldoc.find('object/bndbox/ymax')
    node.text = '0'
    ##以上针对normal
    xmldoc.write(xmlpath+xmllist[i])
    i=i+1
    print(item)


3 数据增强

import os 
import cv2 
import imghdr 
import time 
from PIL import Image, ImageEnhance, ImageOps, ImageFile
import numpy as np


class PreprocessIMG:
    def __init__(self):
        pass
   
    #图像裁剪
    @staticmethod
    def img_resize(img_path):
        im  = cv2.imread(img_path)
        img = cv2.resize(im, (416, 416))
        return img
   
    #图像增强(锐化)
    @staticmethod
    def img_resize_enhance(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        imgRGB = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
        PIL_Img = Image.fromarray(imgRGB)
        PIL_ImgEn = ImageEnhance.Sharpness(PIL_Img).enhance(2.0)
        return PIL_ImgEn
   
    #图像增强(对比度)
    @staticmethod
    def img_resize_contrast(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        imgRGB = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
        PIL_Img = Image.fromarray(imgRGB)
        contrast = ImageEnhance.Contrast(PIL_Img)#获取对比度对象
        contrast_img = contrast.enhance(2.0)#增加对比度
        return contrast_img   
   
   
    #图像降噪
    @staticmethod
    def img_resize_denoise(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        dst = cv2.fastNlMeansDenoisingColored(im,None,10,10,7,21)
        return dst
   
    #均值滤波
    @staticmethod
    def img_resize_blur(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        blur = cv2.blur(im,(3,5))#模板大小3*5
        return blur
   
    #高斯滤波
    @staticmethod
    def img_resize_gauss(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        blur = cv2.GaussianBlur(im,(5,5),0)
        return blur
   
    #中值滤波
    @staticmethod
    def img_resize_media(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416, 416))
        blur = cv2.medianBlur(im,5)
        return blur
   
    #双边滤波
    @staticmethod
    def img_resize_bil(img_path):
        im = cv2.imread(img_path)
#        im = cv2.resize(im, (416,416))
        #滤波领域直径, 空间高斯函数标准差,灰度值相似性标准差
        blur = cv2.bilateralFilter(im,9,75,75)
        return blur
               
       
   
def ProcessIMG(path, newpath):
    if os.path.isdir(path):
        img_names = os.listdir(path)
    else:
        img_names = [path]
    for img_name in img_names:
        print(img_name)
        tem_img_name = os.path.join(path, img_name)
        if tem_img_name.split('.')[1] != "DS_Store":
#            image = PreprocessIMG.img_resize(tem_img_name)
            image = PreprocessIMG.img_resize_enhance(tem_img_name)
#            image = PreprocessIMG.img_resize_contrast(tem_img_name)
#            image = PreprocessIMG.img_resize_denoise(tem_img_name)
#            image = PreprocessIMG.img_resize_blur(tem_img_name)
#            image = PreprocessIMG.img_resize_gauss(tem_img_name)
#            image = PreprocessIMG.img_resize_media(tem_img_name)
#            image = PreprocessIMG.img_resize_bil(tem_img_name)
            image = Image.fromarray(np.uint8(image))
            image.save(newpath + '/' + str(img_name) ,format="jpeg")



if __name__ == '__main__':
#    path = "/Users/sisyphus/py/testfrom1"
#    newpath = "/Users/sisyphus/py/testto1"
    path = "/Users/sisyphus/TianChi/traindata/JPEGraw"
#    path = "/Users/sisyphus/SSD-Tensorflow/VOCtest2018/JPEGImages270Raw"
#    newpath = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImagesTrainAugEnh"
#    newpath = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImages270AugGau"
#    newpath = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImages270AugEnh"
#    newpath = "/Users/sisyphus/SSD-Tensorflow/VOCtest2018/JPEGImages270Enh"#先建立文件夹
#    newpath = "/Users/sisyphus/keras-yolo3/test2"
    newpath = "/Users/sisyphus/TianChi/traindata/JPEGenh"
 
    ProcessIMG(path, newpath)
   
   
           
           
4.修改增强集jpg名称
import re
import os
import time
#str.split(string)分割字符串
#'连接符'.join(list) 将列表组成字符串
def change_name(path):
    global i
    if not os.path.isdir(path) and not os.path.isfile(path):
        return False
    if os.path.isfile(path):
        file_path = os.path.split(path) #分割出目录与文件
        lists = file_path[1].split('.') #分割出文件与文件扩展名
        file_ext = lists[-1] #取出后缀名(列表切片操作)
        img_ext = ['bmp','jpeg','gif','psd','png','jpg']
        if file_ext in img_ext:
            os.rename(path,file_path[0]+'/'+lists[0]+'enh.'+file_ext)##########
            i+=1 #注意这里的i是一个陷阱
        #或者
        #img_ext = 'bmp|jpeg|gif|psd|png|jpg'
        #if file_ext in img_ext:
        #    print('ok---'+file_ext)
    elif os.path.isdir(path):
        for x in os.listdir(path):
            print(x)
            print(os.path.join(path,x))
            change_name(os.path.join(path,x)) #os.path.join()在路径处理上很有用


#img_dir = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImagesTrainAugEnh"
#img_dir = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImagesTrainAugGau"
#img_dir = "/Users/sisyphus/darkflow/VOCtest2018/JPEGImages270AugCon"  
#img_dir = "/Users/sisyphus/SSD-Tensorflow/VOCtest2018/JPEGImages270Enh"
#img_dir = '/Users/sisyphus/darkflow/VOCtest2018/testJPEG/'
#img_dir = img_dir.replace('\\','/')
img_dir = '/Users/sisyphus/TianChi/traindata/JPEGenh'
start = time.time()
i = 0
change_name(img_dir)
c = time.time() - start
print('程序运行耗时:%0.2f'%(c))
print('总共处理了 %s 张图片'%(i))


5修改增强集xml名称
import re
import os
import time
#str.split(string)分割字符串
#'连接符'.join(list) 将列表组成字符串
def change_name(path):
    global i
    if not os.path.isdir(path) and not os.path.isfile(path):
        return False
    if os.path.isfile(path):
        file_path = os.path.split(path) #分割出目录与文件
        lists = file_path[1].split('.') #分割出文件与文件扩展名
        file_ext = lists[-1] #取出后缀名(列表切片操作)
        img_ext = ['xml']
        if file_ext in img_ext:
            os.rename(path,file_path[0]+'/'+lists[0]+'enh.'+file_ext)#######++
            i+=1 #注意这里的i是一个陷阱
        #或者
        #img_ext = 'bmp|jpeg|gif|psd|png|jpg'
        #if file_ext in img_ext:
        #    print('ok---'+file_ext)
    elif os.path.isdir(path):
        for x in os.listdir(path):
            print(x)
            print(os.path.join(path,x))
            change_name(os.path.join(path,x)) #os.path.join()在路径处理上很有用


#img_dir = "/Users/sisyphus/darkflow/VOCtest2018/AnnotationTrainAugEnh"
#img_dir = "/Users/sisyphus/darkflow/VOCtest2018/Annotations270AugCon"#####先修改上面++
#img_dir = "/Users/sisyphus/SSD-Tensorflow/VOCtest2018/Annotations270Enh"
#img_dir = '/Users/sisyphus/darkflow/VOCtest2018/testAnn/'
#img_dir = img_dir.replace('\\','/')
img_dir = '/Users/sisyphus/TianChi/traindata/xmlenh'
start = time.time()
i = 0
change_name(img_dir)
c = time.time() - start
print('程序运行耗时:%0.2f'%(c))
print('总共处理了 %s 份xml'%(i))

6 修改增强集xml内容
from xml.etree import ElementTree
import os

jpgpath="/Users/sisyphus/TianChi/traindata/JPEGenh/"#末尾要加斜杠
jpglist = os.listdir(jpgpath)
jpglist.sort()


xmlpath="/Users/sisyphus/TianChi/traindata/xmlenh/"########
xmllist = os.listdir(xmlpath)
xmllist.sort()

i=0
for item in xmllist:
#    print(item)
    xmldoc = ElementTree.parse(xmlpath+xmllist[i])
    node = xmldoc.find('./filename')
    node.text = jpglist[i]

#    node = xmldoc.find('object/name')
#    node.text = 'normal'    #######################
#    ##以下针对normal
#    node = xmldoc.find('object/bndbox/xmin')
#    node.text = '0' 
#    node = xmldoc.find('object/bndbox/ymin')
#    node.text = '0'
#    node = xmldoc.find('object/bndbox/xmax')
#    node.text = '0'
#    node = xmldoc.find('object/bndbox/ymax')
#    node.text = '0'
#    ##以上针对normal
    xmldoc.write(xmlpath+xmllist[i])
    i=i+1
    print(item)


7 修改Main/txt文件夹
classes='DW' 
classes='MB' 
classes='ZD'
classes='normal'


#xmlfilepath = '/Users/sisyphus/keras-retinanet/VOCdevkit/VOC2018/Annotations/'
#txtsavepath = '/Users/sisyphus/keras-retinanet/VOCdevkit/VOC2018/ImageSets/Main/'  
xmlfilepath = '/Users/sisyphus/TianChi/VOC2018/Annotations/'
txtsavepath = '/Users/sisyphus/TianChi/VOC2018/ImageSets/Main/'
total_xml = os.listdir(xmlfilepath)  
  
num=len(total_xml)  
list=range(num)  
tv=int(num*trainval_percent)  
tr=int(tv*train_percent)  
trainval= random.sample(list,tv)  
train=random.sample(trainval,tr)  
  
ftrainval = open(txtsavepath+'_trainval.txt', 'w')  
ftest = open(txtsavepath+'_test.txt', 'w')  
ftrain = open(txtsavepath+'_train.txt', 'w')  
fval = open(txtsavepath+'_val.txt', 'w')  
  
for i  in list:  
#    name='/Users/sisyphus/keras-retinanet/VOCdevkit/VOC2018/JPEGImages/'+total_xml[i][:-4]+'\n'  
    name=total_xml[i][:-4]+'\n'
    if i in trainval:  
        ftrainval.write(name)  
        if i in train:  
            ftrain.write(name)  
        else:  
            fval.write(name)  
    else:  
        ftest.write(name)  
  
ftrainval.close()  
ftrain.close()  
fval.close()  
ftest .close()

8 修改names文件
在YOLO主目录的data文件夹下,创建一个.names文件,文件名任意。比如mydata.names。在该文件中写入所有类别的名称,每一类占一行。

9 修改data文件
接下来我们要做的是修改YOLO的cfg文件。在darknet的主目录下,进入cfg目录,找到voc.data打开,修改其中的内容
classes= 1           #训练数据的类别数目,我这里只有一类,所以这里是1
train  = <path-to-voc>/train.txt             #上面1.2步骤生成的train文件路径
valid  = <path-to-voc>2007_test.txt         #上面1.2步骤生成的val文件路径
names = data/voc.names                    #上面2.1步骤创建的names文件路径
backup = backup                       #这是训练得到的model的存放目录,建议自己修改。

10 修改cfg
把cfg文夹中的yolov3-voc.cfg复制到自己项目目录下,并修改:
[net]
# Testing
# batch=1
# subdivisions=1    #训练时候把上面Testing的参数注释
# Training
batch=64
subdivisions=32     #这个参数根据自己GPU的显存进行修改,显存不够就改大一些
...                 #因为训练时每批的数量 = batch/subdivisions
...
...
learning_rate=0.001  #根据自己的需求还有训练速度学习率可以调整一下
burn_in=1000
max_batches = 30000  #根据自己的需求还有训练速度max_batches可以调整一下
policy=steps
steps=10000,20000    #跟着max_batches做相应调整
...
...
...
[convolutional]
size=1
stride=1
pad=1
filters=30         #filters = 3*(classes + 5)
activation=linear

[yolo]
mask = 0,1,2
anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
classes=5          #修改类别数
num=9
jitter=.3
ignore_thresh = .5
truth_thresh = 1
random=1           #显存小的话 =0

#这个文件的最下面有3个YOLO层,这里我才放上来了一个,这三个地方的classes做相应修改
#每个YOLO层的上一层的convolutional层的filters也要修改


11 下载预训练模型(权重)
wget https://pjreddie.com/media/files/darknet53.conv.74

12 训练
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74

报错:
Cannot load image /home/ubuntu/fddb/JPEGImages/2002_08_07_big_img_1348.jpg STB Reason: can't fopen

查得可能需要opencv=1,
opencv=1 makefile 报错

 fatal error: opencv2/highgui/highgui_c.h: No such file or directory


还在查找原因中。。



2018年6月13日星期三

keras_yolov3_test_delk

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May 29 10:53:04 2018

@author: sisyphus
"""
import os
import random
import json
import colorsys
import numpy as np
import tensorflow as tf
from keras import backend as K
from keras.models import load_model
from PIL import Image, ImageFont, ImageDraw
from timeit import time


def sigmoid(x):
    y = 1/(1+np.exp(-x))
    return y

def letterbox_image(image, size):
    '''resize image with unchanged aspect ratio using padding'''
    image_w, image_h = image.size
    w, h = size
    new_w = int(image_w * min(w*1.0/image_w, h*1.0/image_h))
    new_h = int(image_h * min(w*1.0/image_w, h*1.0/image_h))
    resized_image = image.resize((new_w,new_h), Image.BICUBIC)

    boxed_image = Image.new('RGB', size, (128,128,128))
    boxed_image.paste(resized_image, ((w-new_w)//2,(h-new_h)//2))
    return boxed_image


def yolo_head(feats, anchors, num_classes, input_shape):
    """Convert final layer features to bounding box parameters."""
    num_anchors = len(anchors)
    anchors_tensor = np.reshape(anchors, [1, 1, 1, num_anchors, 2])#++

    grid_shape = np.shape(feats)[1:3]#++

    grid_y = np.tile(np.reshape(np.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]),
        [1, grid_shape[1], 1, 1])#++
   
    grid_x = np.tile(np.reshape(np.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]),
        [grid_shape[0], 1, 1, 1])#++

    grid = np.concatenate([grid_x, grid_y], axis=-1)#++

    grid = grid.astype(np.float32)#++


    feats = np.reshape(
        feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5])

    box_xy = sigmoid(feats[..., :2])
    box_wh = np.exp(feats[..., 2:4])
    box_confidence = sigmoid(feats[..., 4:5])
    box_class_probs = sigmoid(feats[..., 5:])

    box_xy = (box_xy + grid) / grid_shape[::-1]
    box_wh = box_wh * anchors_tensor / input_shape[::-1]

    return box_xy, box_wh, box_confidence, box_class_probs


def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape):
    '''Get corrected boxes'''
    box_yx = box_xy[..., ::-1]
    box_hw = box_wh[..., ::-1]

    mm = min(input_shape[0]/image_shape[0],input_shape[1]/image_shape[1])#++
    image_shape = [image_shape[0]*mm, image_shape[1]*mm]#++
    new_shape = [round(image_shape[0]),round(image_shape[1])]#++
    offset = (input_shape[0]-new_shape[0])/2./input_shape[0]
    scale = input_shape[0]/new_shape[0]
    box_yx = (box_yx - offset) * scale
    box_hw *= scale

    box_mins = box_yx - (box_hw / 2.)
    box_maxes = box_yx + (box_hw / 2.)

    boxes =  np.concatenate([
        box_mins[..., 0:1],  # y_min
        box_mins[..., 1:2],  # x_min
        box_maxes[..., 0:1],  # y_max
        box_maxes[..., 1:2]  # x_max
    ],axis = -1)

    # Scale boxes back to original image shape.
    boxes *= np.concatenate([image_shape, image_shape],axis = -1)
    return boxes


def yolo_boxes_and_scores(feats, anchors, num_classes, input_shape, image_shape):
    '''Process Conv layer output'''
    box_xy, box_wh, box_confidence, box_class_probs = yolo_head(feats,
        anchors, num_classes, input_shape)
    boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape)
    boxes = np.reshape(boxes, [-1, 4])
    box_scores = box_confidence * box_class_probs
    box_scores = np.reshape(box_scores, [-1, num_classes])
    return boxes, box_scores

def nms(bounding_boxes, confidence_score, threshold):
    # If no bounding boxes, return empty list
    if len(bounding_boxes) == 0:
        return [], []
    # coordinates of bounding boxes
    start_x = bounding_boxes[:, 0]
    start_y = bounding_boxes[:, 1]
    end_x = bounding_boxes[:, 2]
    end_y = bounding_boxes[:, 3]

    # Picked bounding boxes
    picked_boxes = []
    picked_score = []
    index_b = []

    # Compute areas of bounding boxes
    areas = (end_x - start_x + 1) * (end_y - start_y + 1)

    # Sort by confidence score of bounding boxes
    score = np.array(confidence_score)
    order = np.argsort(score)
    # Iterate bounding boxes
    while order.size > 0:
        # The index of largest confidence score
        index = order[-1]
        # Pick the bounding box with largest confidence score
        picked_boxes.append(bounding_boxes[index])
        picked_score.append(confidence_score[index])
        index_b.append(index)

        # Compute ordinates of intersection-over-union(IOU)
        x1 = np.maximum(start_x[index], start_x[order[:-1]])
        x2 = np.minimum(end_x[index], end_x[order[:-1]])
        y1 = np.maximum(start_y[index], start_y[order[:-1]])
        y2 = np.minimum(end_y[index], end_y[order[:-1]])

        # Compute areas of intersection-over-union
        w = np.maximum(0.0, x2 - x1 + 1)
        h = np.maximum(0.0, y2 - y1 + 1)
        intersection = w * h

        # Compute the ratio between intersection and union
        ratio = intersection / (areas[index] + areas[order[:-1]] - intersection)

        left = np.where(ratio < threshold)
        order = order[left]
    return index_b


def boolean_mask(N,M):
    ax = N.shape[0]
    id=[]
    for i in range(0,ax):
        j=i*M[i]
        id.append(j)
    boxes=[]
   
    for k in range(0,ax):
        if id[k]!=0:
            box=N[k]
            boxes.append(box)
    return np.array(boxes)


def yolo_eval(yolo_outputs,
              anchors,
              num_classes,
              image_shape,
              max_boxes=20,
              score_threshold=.6,
              iou_threshold=.5):
    """Evaluate YOLO model on given input and return filtered boxes."""
    anchor_mask = [[6,7,8], [3,4,5], [0,1,2]]
    input_shape = np.shape(yolo_outputs[0])[1]*32, np.shape(yolo_outputs[0])[2]*32  #++
    boxes = []
    box_scores = []
    for l in range(3):
        _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l],
            anchors[anchor_mask[l]], num_classes, input_shape, image_shape)
        boxes.append(_boxes)
        box_scores.append(_box_scores)
    boxes = np.concatenate(boxes, axis=0)
    boxes = boxes.astype(np.float32)#++
    box_scores = np.concatenate(box_scores, axis=0)

    mask = box_scores >= score_threshold
    boxes_ = []
    scores_ = []
    classes_ = []
    for c in range(num_classes):
        class_boxes = boolean_mask(boxes, mask[:, c])
        if np.shape(class_boxes)[0] == 0:
            continue
        class_box_scores = boolean_mask(box_scores[:, c], mask[:, c])
        nms_index = nms(class_boxes, class_box_scores, iou_threshold)#++
        class_boxestt_=[]
        class_box_scorestt_=[]
        classestt_=[]
        for i in nms_index:
            class_boxestt = class_boxes[i]
            class_box_scorestt = class_box_scores[i]
            classestt = c
            class_boxestt_.append(class_boxestt)
            class_box_scorestt_.append(class_box_scorestt)
            classestt_.append(classestt)
        boxes_.append(class_boxestt_)
        scores_.append(class_box_scorestt_)
        classes_.append(classestt_)
    if np.shape(boxes_)[0] == 0:
        return [],[],[]
    else:
#        return boxes_[0], scores_[0], classes_[0]
        return boxes_, scores_, classes_




def get_anchors(anchors_path):
    '''
    获取anchors
    '''
    anchors_path = os.path.expanduser(anchors_path)
    with open(anchors_path) as f:
        anchors = f.readline()
        anchors = [float(x) for x in anchors.split(',')]
        anchors = np.array(anchors).reshape(-1, 2)
    return anchors

def get_class(classes_path):
    '''
    获取检测类别
    '''
    classes_path = os.path.expanduser(classes_path)
    with open(classes_path) as f:
        class_names = f.readlines()
    class_names = [c.strip() for c in class_names]
    return class_names


def postprocess(image, result):
    '''
    后处理函数
    输入:待检测图片image,yolo网络输出result(3组向量,对应3组anchors)
    输出:检测信息json(保存在文件夹),带标注框带图片image(作为函数返回值)
    '''
    start = time.time()
    anchors_path = 'model_data/yolo_anchors.txt'
    classes_path = 'model_data/voc_6c_classes.txt'
    score = 0.3
    iou = 0.5
    input_image_shape = [image.size[1], image.size[0]]
#    anchors = get_anchors(anchors_path)
    anchors=np.array([[ 10.,  13.],
                      [ 16.,  30.],
                      [ 33.,  23.],
                      [ 30.,  61.],
                      [ 62.,  45.],
                      [ 59., 119.],
                      [116.,  90.],
                      [156., 198.],
                      [373., 326.]])
#    class_names = get_class(classes_path)
    class_names = ['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled-in_scale', 'scratches']

    out_boxes, out_scores, out_classes = yolo_eval(result,
                                                   anchors,
                                                   len(class_names),
                                                   input_image_shape,
                                                   score_threshold=score,
                                                   iou_threshold=iou)
    out_boxes, out_scores, out_classes = sum(out_boxes, []),sum(out_scores, []),sum(out_classes, [])
    print('Found {} boxes for {}'.format(len(out_boxes), 'img'))
    font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
                    size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
    thickness = (image.size[0] + image.size[1]) // 300
   
   
    # Generate colors for drawing bounding boxes.
    hsv_tuples = [(x / len(class_names), 1., 1.)
                     for x in range(len(class_names))]
    colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
    colors = list(
        map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
            colors))
    random.seed(10101)  # Fixed seed for consistent colors across runs.
    random.shuffle(colors)  # Shuffle colors to decorrelate adjacent classes.
    random.seed(None)  # Reset seed to default.

    resultsForJSON = []#+++   
   
    for i, c in reversed(list(enumerate(out_classes))):
        predicted_class = class_names[c]
        box = out_boxes[i]
        score = out_scores[i]
        label = '{} {:.2f}'.format(predicted_class, score)
        draw = ImageDraw.Draw(image)
        label_size = draw.textsize(label, font)
        top, left, bottom, right = box/2  #++
        top = max(0, np.floor(top + 0.5).astype('int32'))
        left = max(0, np.floor(left + 0.5).astype('int32'))
        bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
        right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
        print(label, (left, top), (right, bottom))
           
        area=(bottom-top)*(right-left)#####+
        resultsForJSON.append({"label": predicted_class,\
                               "confidence": float('%.2f' % score),\
                               "topleft": {"x": float(left), "y": float(top)},\
                               "bottomright": {"x": float(right), "y": float(bottom)},\
                               "area":float(area)})       
        if top - label_size[1] >= 0:
            text_origin = np.array([left, top - label_size[1]])
        else:
            text_origin = np.array([left, top + 1])
           
        for i in range(thickness):
            draw.rectangle(
                [left + i, top + i, right - i, bottom - i],
                outline=colors[c])
        draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=colors[c])
        draw.text(text_origin, label, fill=(0, 0, 0), font=font)
        del draw

    end = time.time()
    print(end - start)
    ####################保存json##########start
    print(resultsForJSON)
    imgdir = "/Users/sisyphus/keras_yolo3_model/"    ###########+路径也要修改
    outfolder = os.path.join(imgdir, 'out')
    img_name = os.path.join(outfolder, os.path.basename(pathall))
    if resultsForJSON == []:
        resultsForJSON.append({"label": "Normal",\
                               "confidence": float(0), \
                               "topleft": {"x": float(0), "y": float(0)}, \
                               "bottomright": {"x": float(0), "y": float(0)},\
                               "area":float(0)})
        textJSON = json.dumps(resultsForJSON)
        textFile = os.path.splitext(img_name)[0] + ".json"
        print('\n')
        with open(textFile, 'w') as f:
            f.write(textJSON)
        print('Normal\n')
    else:
        textJSON = json.dumps(resultsForJSON)
        textFile = os.path.splitext(img_name)[0] + ".json"
        print(textFile)
        print('\n')
        with open(textFile, 'w') as f:
            f.write(textJSON)
    ####################保存json##########end     
    return image



imgdir = "/Users/sisyphus/keras_yolo3_model/"    #模型存放路径
outfolder = os.path.join(imgdir, 'out')          #处理后图片和json保存路径
path = "/Users/sisyphus/keras_yolo3_model/sample_img_test2"    #待处理图片存放路径
model_path = 'model_data/yolo.h5'
print("Loading model......")
yolo_model = load_model(model_path, compile=False)   #加载模型
print("Model loaded successful")

for xd in os.listdir(path):
#    xd = os.listdir(path)[0]
    pathall = os.path.join(path,xd)
    image = Image.open(pathall)
    boxed_image = letterbox_image(image, tuple(reversed((416, 416))))
    image_data = np.array(boxed_image, dtype='float32')
    print(image_data.shape)
    image_data /= 255.
    image_data = np.expand_dims(image_data, 0) 
#    input_image_shape = K.placeholder(shape=(2, ))
    result = yolo_model.predict(image_data)    #模型推导
#    result = result[0]
    imgpost = postprocess(image, result)       #后处理函数
    img_name = os.path.join(outfolder, os.path.basename(pathall))
    imgpost.save(img_name)       #保存处理后的图片


   




Failed to find TIFF library

ImportError: Failed to find TIFF library. Make sure that libtiff is installed and its location is listed in PATH|LD_LIBRARY_PATH|.. 解决方法: ...