我的基本环境:python3.6、pytorch1.8.1、cuda10.1、cudnn7.6、vs2019
cuda自己装,这里是我的cuda10.1
需要安装vs2019
,使用它进行编译,必须在命令行可以使用cl.exe。不能用就是没在系统环境里。
我的系统环境变量如下,为了省事我直接把vs2019装c盘了,emmm,结果c盘空间不够了。。。
# 最好还是使用3.6的python吧
conda create -n detectron2 python=3.6
conda activate detectron2
# 这里我已经有了清华的conda镜像,就直接输入下面的命令,然后自动安装了pytorch1.8.1
conda install pytorch torchvision cudatoolkit=10.1
# 如下是安装的一些包,我截了一部分出来
###################################################################
---------------------------|-----------------
msys2-conda-epoch-20160418 | 1 3 KB https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
ninja-1.7.2 | 0 1.8 MB http://mirror.tuna.tsinghua.edu.cn/anaconda/pkgs/free
numpy-1.19.2 | py36hadc3359_0 22 KB http://mirror.tuna.tsinghua.edu.cn/anaconda/pkgs/main
pytorch-1.8.1 | py3.6_cuda10.1_cudnn7_0 836.5 MB http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch
sqlite-3.35.3 | h2bbff1b_0 761 KB http://mirror.tuna.tsinghua.edu.cn/anaconda/pkgs/main
torchvision-0.9.1 | py36_cu101 7.3 MB http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch
vc-14.2 | h21ff451_1
安装好检查下环境,激活detectron2环境后输入python进入它的命令行
>>> import torch
>>> torch.__version__
'1.8.1'
>>> torch.version.cuda
'10.1'
>>> torch.backends.cudnn.version()
7604
>>> torch.cuda.is_available()
True
# 到github搞到源码
git clone https://github.com/facebookresearch/detectron2.git
# 太慢的话使用镜像
git clone https://github.com.cnpmjs.org/facebookresearch/detectron2.git
detectron2的安装程序里需要如下依赖,版本要求貌似有点严。
install_requires=[
# Do not add opencv here. Just like pytorch, user should install
# opencv themselves, preferrably by OS's package manager, or by
# choosing the proper pypi package name at https://github.com/skvark/opencv-python
"termcolor>=1.1",
"Pillow>=7.1", # or use pillow-simd for better performance
"yacs>=0.1.6",
"tabulate",
"cloudpickle",
"matplotlib",
"tqdm>4.29.0",
"tensorboard",
# Lock version of fvcore/iopath because they may have breaking changes
# NOTE: when updating fvcore/iopath version, make sure fvcore depends
# on the same version of iopath.
"fvcore>=0.1.5,<0.1.6", # required like this to make it pip installable
"iopath>=0.1.7,<0.1.8",
"pycocotools>=2.0.2", # corresponds to https://github.com/ppwwyyxx/cocoapi
"future", # used by caffe2
"pydot", # used to save caffe2 SVGs
"dataclasses; python_version<'3.7'",
"omegaconf==2.1.0.dev22",
# When adding to the list, may need to update docs/requirements.txt
# or add mock in docs/conf.py
],
因为直接运行setup.py安装依赖太慢了,所以我用清华镜像,为了避免意外我一个一个直接复制装的。然后其中我安装fvcore使用pip install fvcore==0.1.5
,它顺便也装上了iopath 0.1.8
,貌似和要求不符,但是我没管它。这个dataclasses; python_version<'3.7'
,就是看到它我才没选择python3.7。
这里图方便也可以运行下面命令一键安装依赖,网络好的话应该没问题。
pip install termcolor>=1.1 Pillow>=7.1 yacs>=0.1.6 tabulate cloudpickle matplotlib tqdm>4.29.0 tensorboard fvcore==0.1.5 iopath==0.1.8 future pydot dataclasses omegaconf==2.1.0.dev22 cython opencv-python
然后安装pycocotools2.0.2有点问题,我直接clone的代码里说的cocoapi,即 https://github.com/ppwwyyxx/cocoapi这个
进入cocoapi\PythonAPI目录下运行python setup.py build_ext install
,从代码可以看到在windows安装就啥编译条件都没有,但是还报错找不到maskApi.c啥的。看源码知道在common目录里,但它是一个文件,打开一看,内容如下
emmm,给’./common’多加一个点,运行就完事了。如图所示
在编译前修改cpp_extension.py,大概在D:\Anaconda3\envs\detectron2\lib\site-packages\torch\utils\cpp_extension.py
第300行
match = re.search(r'(\d+)\.(\d+)\.(\d+)', compiler_info.decode("utf8","ignore").strip())
然后进入detectron2目录运行python setup.py build develop
结果出了一堆,然后报错
File "D:\Anaconda3\envs\detectron2\lib\distutils\command\build_ext.py", line 448, in build_extensions
self._build_extensions_serial()
File "D:\Anaconda3\envs\detectron2\lib\distutils\command\build_ext.py", line 473, in _build_extensions_serial
self.build_extension(ext)
File "D:\Anaconda3\envs\detectron2\lib\site-packages\setuptools\command\build_ext.py", line 196, in build_extension
_build_ext.build_extension(self, ext)
File "D:\Anaconda3\envs\detectron2\lib\distutils\command\build_ext.py", line 533, in build_extension
depends=ext.depends)
File "D:\Anaconda3\envs\detectron2\lib\site-packages\torch\utils\cpp_extension.py", line 690, in win_wrap_ninja_compile
with_cuda=with_cuda)
File "D:\Anaconda3\envs\detectron2\lib\site-packages\torch\utils\cpp_extension.py", line 1359, in _write_ninja_file_and_compile_objects
error_prefix='Error compiling objects for extension')
File "D:\Anaconda3\envs\detectron2\lib\site-packages\torch\utils\cpp_extension.py", line 1683, in _run_ninja_build
raise RuntimeError(message) from e
RuntimeError: Error compiling objects for extension
仔细翻了一下找到error的地方:
D:/Anaconda3/envs/detectron2/lib/site-packages/torch/include\c10/util/Half-inl.h(31): error: identifier "__floorf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(146): error: calling a __host__ function("__floorf") from a __device__ function("get_gradient_weight " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(146): error: identifier "__floorf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(147): error: calling a __host__ function("__floorf") from a __device__ function("get_gradient_weight " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(147): error: identifier "__floorf" is undefined in device code
D:/Anaconda3/envs/detectron2/lib/site-packages/torch/include\c10/util/Half-inl.h(31): error: calling a __host__ function("__floorf") from a __device__ function("get_gradient_weight< ::c10::Half> ") is not allowed
D:/Anaconda3/envs/detectron2/lib/site-packages/torch/include\c10/util/Half-inl.h(31): error: identifier "__floorf" is undefined in device code
D:/Anaconda3/envs/detectron2/lib/site-packages/torch/include\c10/util/Half-inl.h(31): error: calling a __host__ function("__floorf") from a __device__ function("get_gradient_weight< ::c10::Half> ") is not allowed
D:/Anaconda3/envs/detectron2/lib/site-packages/torch/include\c10/util/Half-inl.h(31): error: identifier "__floorf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(178): error: calling a __host__ function("__floorf") from a __device__ function("get_coordinate_weight " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(178): error: identifier "__floorf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/deformable/deform_conv_cuda_kernel.cu(179): error: calling a __host__ function("__floorf") from a __device__ function("get_coordinate_weight " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(185): error: calling a __host__ function("__ceilf") from a __global__ function("detectron2::RoIAlignRotatedForward " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(185): error: identifier "__ceilf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(188): error: calling a __host__ function("__ceilf") from a __global__ function("detectron2::RoIAlignRotatedForward " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(188): error: identifier "__ceilf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(271): error: calling a __host__ function("__ceilf") from a __global__ function("detectron2::RoIAlignRotatedBackwardFeature " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(271): error: identifier "__ceilf" is undefined in device code
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(274): error: calling a __host__ function("__ceilf") from a __global__ function("detectron2::RoIAlignRotatedBackwardFeature " ) is not allowed
D:/ubuntu/detectron2/detectron2/layers/csrc/ROIAlignRotated/ROIAlignRotated_cuda.cu(274): error: identifier "__ceilf" is undefined in device code
发现是什么__ceilf
和__floorf
的问题,然后找到ROIAlignRotated_cuda.cu
和deform_conv_cuda_kernel.cu
文件,把里面的ceil
和floor
后面都加上f
就完事,即ceil
改为ceilf
、floor
改为floorf
。具体原理我也不知道,不过可别一下子全替换,有些函数名里也包含这个,一个一个替换最好。
之后再次运行安装,完事!
python setup.py build develop
...
Finished processing dependencies for detectron2==0.4
有图为证
请看我的pip list
absl-py (0.12.0)
antlr4-python3-runtime (4.8)
cachetools (4.2.1)
certifi (2020.12.5)
chardet (4.0.0)
cloudpickle (1.6.0)
cycler (0.10.0)
Cython (0.29.22)
dataclasses (0.8)
detectron2 (0.4, d:\ubuntu\detectron2)
future (0.18.2)
fvcore (0.1.5.post20210330)
google-auth (1.28.0)
google-auth-oauthlib (0.4.4)
grpcio (1.36.1)
idna (2.10)
importlib-metadata (3.10.0)
iopath (0.1.8)
kiwisolver (1.3.1)
Markdown (3.3.4)
matplotlib (3.3.4)
mkl-fft (1.3.0)
mkl-random (1.1.1)
mkl-service (2.3.0)
numpy (1.19.2)
oauthlib (3.1.0)
olefile (0.44)
omegaconf (2.1.0.dev22)
opencv-python (4.5.1.48)
Pillow (8.1.2)
pip (9.0.1)
portalocker (2.3.0)
protobuf (3.15.6)
pyasn1 (0.4.8)
pyasn1-modules (0.2.8)
pycocotools (2.0.2)
pydot (1.4.2)
pyparsing (2.4.7)
python-dateutil (2.8.1)
pywin32 (300)
PyYAML (5.4.1)
requests (2.25.1)
requests-oauthlib (1.3.0)
rsa (4.7.2)
setuptools (54.2.0)
six (1.10.0)
tabulate (0.8.9)
tensorboard (2.4.1)
tensorboard-plugin-wit (1.8.0)
termcolor (1.1.0)
torch (1.8.1)
torchvision (0.9.1)
tqdm (4.59.0)
typing-extensions (3.7.4.3)
urllib3 (1.26.4)
Werkzeug (1.0.1)
wheel (0.29.0)
wincertstore (0.2)
yacs (0.1.8)
zipp (3.4.1)
测试视频识别的demo,运行
python demo/demo.py --config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml --webcam --opts MODEL.WEIGHTS model_final_a54504.pkl`
# model_final_a54504.pkl 官网下载地址: https://dl.fbaipublicfiles.com/detectron2/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x/137260431/model_final_a54504.pkl
测试一张图,运行
python demo/demo.py --config-file configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml --input 1.jpg --opts MODEL.WEIGHTS model_final_a54504.pkl
训练自己的数据集,在预训练模型上只迭代100次
然后识别草莓,emmm,大功告成。
训练和预测代码是我师兄给的(我只是个菜鸡,代码还没懂。。。),这里附上。先用changemaskrcnn.py生成自己的预训练模型,然后运行train.py训练即可。
changemaskrcnn.py
import numpy as np
import pickle
num_class = 1 # 修改为自己的类别,不包括背景
with open('model_final_a54504.pkl', 'rb') as f:
obj = f.read()
weights = pickle.loads(obj, encoding='latin1')
weights['model']['roi_heads.box_predictor.cls_score.weight']=np.zeros([num_class+1,1024], dtype='float32')
weights['model']['roi_heads.box_predictor.cls_score.bias']=np.zeros([num_class+1], dtype='float32')
weights['model']['roi_heads.box_predictor.bbox_pred.weight']=np.zeros([num_class*4,1024], dtype='float32')
weights['model']['roi_heads.box_predictor.bbox_pred.bias']=np.zeros([num_class*4], dtype='float32')
weights['model']['roi_heads.mask_head.predictor.weight']=np.zeros([num_class,256,1,1], dtype='float32')
weights['model']['roi_heads.mask_head.predictor.bias']=np.zeros([num_class], dtype='float32')
f = open('model_final_maskrcnn.pkl', 'wb')
pickle.dump(weights, f)
f.close()
train.py
from detectron2.utils.logger import setup_logger
setup_logger()
import cv2
import random
import os
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog
from detectron2.data.datasets import register_coco_instances
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.engine import DefaultTrainer
from detectron2.config import get_cfg
def train():
register_coco_instances("custom", {}, "datasets/coco/annotations/instances_train2017.json", "datasets/coco/train2017")
# 看自己标注的图
# custom_metadata = MetadataCatalog.get("custom")
# dataset_dicts = DatasetCatalog.get("custom")
# for d in random.sample(dataset_dicts, 3):
# img = cv2.imread(d["file_name"])
# visualizer = Visualizer(img[:, :, ::-1], metadata=custom_metadata, scale=1)
# vis = visualizer.draw_dataset_dict(d)
# cv2.imshow('Sample',vis.get_image()[:, :, ::-1])
# cv2.waitKey()
cfg = get_cfg()
cfg.merge_from_file(
"configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml"
)
cfg.DATASETS.TRAIN = ("custom",)
cfg.DATASETS.TEST = ()
cfg.DATALOADER.NUM_WORKERS = 4
cfg.MODEL.WEIGHTS = 'model_final_maskrcnn.pkl'
cfg.SOLVER.IMS_PER_BATCH = 2
cfg.SOLVER.BASE_LR = 0.02
cfg.SOLVER.MAX_ITER = (
100
)
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = (
128
)
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # 修改为自己的类别,不包括背景
os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)
trainer = DefaultTrainer(cfg)
trainer.resume_or_load(resume=False)
trainer.train()
if __name__ == "__main__":
train()
predict.py
from detectron2.utils.logger import setup_logger
setup_logger()
import cv2
import os
from detectron2.engine import DefaultPredictor
from detectron2.config import get_cfg
from detectron2.utils.visualizer import Visualizer
from detectron2.data import MetadataCatalog
from detectron2.data.datasets import register_coco_instances
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.config import get_cfg
def predict():
register_coco_instances("custom", {}, "datasets/coco/annotations/instances_train2017.json", "datasets/coco/train2017")
custom_metadata = MetadataCatalog.get("custom")
DatasetCatalog.get("custom")
im = cv2.imread("1.jpg")
cfg = get_cfg()
cfg.merge_from_file("configs/COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_1x.yaml")
cfg.DATASETS.TEST = ("custom", )
cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth")
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = (
128
)
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # 修改为自己的类别,不包括背景
predictor = DefaultPredictor(cfg)
outputs = predictor(im)
v = Visualizer(im[:, :, ::-1],
metadata=custom_metadata,
scale=1
#instance_mode=ColorMode.IMAGE_BW # remove the colors of unsegmented pixels
)
v = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2.imshow('Result',v.get_image()[:, :, ::-1])
cv2.waitKey()
if __name__ == "__main__":
predict()