C++Python版Mask-R-CNNを呼び出しパラメータを渡して受信する

43496 ワード

Mask R-CNNで人だけを検出するdemoを作ろうとすると、githubはすでにPythonで実現している人がいることに気づいたが、後処理はC++なので、直接C++器でpythonを呼び出し、必要な結果をC++に返したい.
実行環境:
Visual Studio 2015,Python3.6(Anaconda),OpenCV3.4.2(C++),tensorflow1.12,Keras2.0.8
C++環境構成
  • 配置OpenCV
  • 新しいC++プロジェクト;
  • 右クリック属性→rightarrow→C++ディレクトリ→rightarrow→ディレクトリを含む→rightarrow→編集をクリックし、
    D:\Programs\opencv\build\include
    D:\Programs\opencv\build\include\opencv
    D:\Programs\opencv\build\include\opencv2
    
    をディレクトリを含むディレクトリに追加し、構成されたシナリオプラットフォームバージョンと現在実行されている一致**に注意する.
  • 右クリック属性→rightarrow→C++ディレクトリ→rightarrow→ライブラリディレクトリ→rightarrow→編集をクリックし、
    D:\Programs\opencv\build\x64\vc14\lib
    
    をライブラリディレクトリに追加し、VSのバージョンに注意し、2017はvc 15のディレクトリに変更する.
  • 右クリック属性→rightarrow→リンク→rightarrow→入力→rightarrow→編集をクリックし、
    opencv_world342.lib
    
    を追加します.
  • Python環境
  • の構成
  • 右クリック属性→rightarrow→C++ディレクトリ→rightarrow→ディレクトリを含む→rightarrow→編集をクリックし、
    D:\Programs\Anaconda3\include
    D:\Programs\Anaconda3\Lib\site-packages
    umpy\core\include
    を含むディレクトリに追加します.
  • 右クリック属性→rightarrow→C++ディレクトリ→rightarrow→ライブラリディレクトリ→rightarrow→編集をクリックし、
    D:\Programs\Anaconda3\libs
    D:\Programs\Anaconda3\Lib\site-packages
    umpy\core\lib
    をライブラリディレクトリに追加します.
  • 右クリック属性→rightarrow→リンク→rightarrow→入力→rightarrow→編集をクリックし、
    python36.lib
    
    を加えます.python 36のみでpython 36 dがないので、デバッグ時にreleseのバージョンを使うと、debugのバージョンが間違って報告されます.

  • Pythonを呼び出す
  • C++からピクチャデータを入力C++でOpenCVで読み取ったピクチャフォーマットとMask R-CNNの入力フォーマットが異なるため、まずC++でピクチャを処理し、Pythonに渡す必要がある.
    Mat img = imread("./image.jpg");
    auto sz = img.size();
    int x = sz.width;
    int y = sz.height;
    int z = img.channels();
    uchar *CArrays = new uchar[x*y*z];
    int iChannels = img.channels();
    int iRows = img.rows;
    int iCols = img.cols * iChannels;
    if (img.isContinuous())
    {
        iCols *= iRows;
        iRows = 1;
    }
    uchar* p;
    int id = -1;
    for (int i = 0; i < iRows; i++)
    {
        // get the pointer to the ith row
        p = img.ptr<uchar>(i);
        // operates on each pixel
        for (int j = 0; j < iCols; j++)
        {
            CArrays[++id] = p[j];//    
        }
    }
    npy_intp Dims[3] = {y, x, z}; //        !
    PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays);
    
  • Mask R-CNN
    //   python
    Py_Initialize();
    import_array();
    
    PyRun_SimpleString("import sys");
    	PyRun_SimpleString("sys.path.append(r'C:\\Users\\Administrator\\Documents\\Keypoints-of-humanpose-with-Mask-R-CNN-master')");
    
    //  python     
    PyObject *pModule = NULL;
    PyObject *pFunc = NULL;
    PyObject *pArg = NULL;
    PyObject *result = NULL;
    PyObject *pDict = NULL;
    
    //    python  
    PyRun_SimpleString("print('python start')");
    
    PyObject *ArgList = PyTuple_New(1);
    .
    .
    .
    PyTuple_SetItem(ArgList, 0, PyArray);
    
    //    
    pModule = PyImport_ImportModule("human_detected");
    
    if (!pModule)
    {
        cout << "Import Module Failed" << endl;
        system("pause");
        return 0;
    }
    
    //        
    pDict = PyModule_GetDict(pModule);
    
    //          
    pFunc = PyObject_GetAttrString(pModule, "detect");
    .
    .
    .
    
  • を呼び出す
  • Mask R-CNNパラメータを受け入れ、値Mask R-CNN検出者のプロジェクトアドレスを返します.https://github.com/Junyuan12/Mask_RCNN_HumanposeMask R-CNNの配置は詳しく言わないで、ネット上で多くのチュートリアルがあって、主にwindowsの下でpycocoolsを配置するのは問題があるかもしれなくて、windowsの下でpycocoolsのインストールのチュートリアル:https://blog.csdn.net/qq_29592829/article/details/82877494Mask R-CNNにpyファイルを新規作成し、human_detected.py
    import os
    import sys
    import random
    import math
    import numpy as np
    import skimage.io
    import matplotlib
    import matplotlib.pyplot as plt
    
    import coco
    import utils
    import model as modellib
    import visualize
    from model import log
    import cv2
    
    def detect(image):
    	# print(image)
    	ROOT_DIR = os.getcwd()
    	# Directory to save logs and trained model
    	MODEL_DIR = os.path.join(ROOT_DIR, "mylogs")
    
    	# Local path to trained weights file
    	COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco_humanpose.h5")
    	# Download COCO trained weights from Releases if needed
    	if not os.path.exists(COCO_MODEL_PATH):
    	    utils.download_trained_weights(COCO_MODEL_PATH)
    
    	class InferenceConfig(coco.CocoConfig):
    	    GPU_COUNT = 1
    	    IMAGES_PER_GPU = 1
    	    KEYPOINT_MASK_POOL_SIZE = 7
    
    	inference_config = InferenceConfig()
    
    	# Recreate the model in inference mode
    	model = modellib.MaskRCNN(mode="inference", 
    	                          config=inference_config,
    	                          model_dir=MODEL_DIR)
    
    	# Get path to saved weights
    
    	model_path = os.path.join(ROOT_DIR, "mask_rcnn_coco_humanpose.h5")
    	assert model_path != "", "Provide path to trained weights"
    	print("Loading weights from ", model_path)
    	model.load_weights(model_path, by_name=True)
    
    	# COCO Class names
    	#For human pose task We just use "BG" and "person"
    	class_names = ['BG', 'person']
    
    	#BGR->RGB
    	image = image[:,:,::-1]
    	#print(np.shape(image))
    
    	# Run detection
    	results = model.detect_keypoint([image], verbose=1)
    	r = results[0] # for one image
    
    	log("rois",r['rois'])
    	log("keypoints",r['keypoints'])
    	log("class_ids",r['class_ids'])
    	log("keypoints",r['keypoints'])
    	log("masks",r['masks'])
    	log("scores",r['scores'])
    
    	visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], 
    	                            class_names, r['scores'])
    	flat_roi = r['rois'].flatten()
    	print(flat_roi)
     
    	return flat_roi
    
    には、C++から送信された画像を受信し、最終的には一人当たりのdetect(image)に戻る関数roiが含まれている.
  • C++受入返却パラメータpython結果を一列に展開し、C++受入返却の一次元配列出力:
    //          ,     
    PyObject *pReturn = PyObject_CallObject(pFunc, ArgList);
    
    //  python       
    //                 
    if (pReturn)
    {
        //              
        PyArrayObject *pyResultArr = (PyArrayObject *)pReturn;
    
        // Python  PyArrayObject        c double  。
        int *resDataArr = (int *)PyArray_DATA(pyResultArr);
        int dimNum = PyArray_NDIM(pyResultArr);//        ,    1
        npy_intp *pdim = PyArray_DIMS(pyResultArr);//              
    
        //             
        for (int i = 0; i < dimNum; ++i)
        {
            for (int j = 0; j < pdim[0]; ++j)
                cout << resDataArr[i * pdim[0] + j] << ",";
        }
            cout << endl;
    }
    
  • 完全なコードは、次の
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    int main(int argc, char* argv[])
    
    {
    	cv::Mat img = cv::imread("./image.jpg");
    	//   python
    	Py_Initialize();
    	import_array();
    
    	PyRun_SimpleString("import sys");
    	PyRun_SimpleString("sys.path.append(r'C:\\Users\\Administrator\\Documents\\Keypoints-of-humanpose-with-Mask-R-CNN-master')");
    	//PyRun_SimpleString("print(sys.path)");
    
    	//  python     
    
    	PyObject *pModule = NULL;
    	PyObject *pFunc = NULL;
    	PyObject *pArg = NULL;
    	PyObject *result = NULL;
    	PyObject *pDict = NULL;
    
    	//    python  
    	PyRun_SimpleString("print('python start')");
    
    	PyObject *ArgList = PyTuple_New(1);
    
    	auto sz = img.size();
    	int x = sz.width;
    	int y = sz.height;
    	int z = img.channels();
    	uchar *CArrays = new uchar[x*y*z];
    	int iChannels = img.channels();
    	int iRows = img.rows;
    	int iCols = img.cols * iChannels;
    	if (img.isContinuous())
    	{
    		iCols *= iRows;
    		iRows = 1;
    	}
    
    	uchar* p;
    	int id = -1;
    	for (int i = 0; i < iRows; i++)
    	{
    		// get the pointer to the ith row
    		p = img.ptr<uchar>(i);
    		// operates on each pixel
    		for (int j = 0; j < iCols; j++)
    		{
    			CArrays[++id] = p[j];//    
    		}
    	}
    
    	npy_intp Dims[3] = { y, x, z }; //        !
    	PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_UBYTE, CArrays);
    	PyTuple_SetItem(ArgList, 0, PyArray);
    
    	//    
    	pModule = PyImport_ImportModule("human_detected");
    
    	if (!pModule)
    	{
    		cout << "Import Module Failed" << endl;
    		system("pause");
    		return 0;
    	}
    
    	//        
    	pDict = PyModule_GetDict(pModule);
    
    	//          
    	pFunc = PyObject_GetAttrString(pModule, "detect");
    
    	//          ,     
    	PyObject *pReturn = PyObject_CallObject(pFunc, ArgList);
    
    	//  python       
    	//                 
    	if (pReturn) {
    		//              
    		PyArrayObject *pyResultArr = (PyArrayObject *)pReturn;
    
    		// Python  PyArrayObject        c double  。
    		int *resDataArr = (int *)PyArray_DATA(pyResultArr);
    		int dimNum = PyArray_NDIM(pyResultArr);//        ,    1
    		npy_intp *pdim = PyArray_DIMS(pyResultArr);//              
    
    												   //             
    		for (int i = 0; i < dimNum; ++i) {
    			for (int j = 0; j < pdim[0]; ++j)
    				cout << resDataArr[i * pdim[0] + j] << ",";
    		}
    		cout << endl;
    	}
    
    	PyRun_SimpleString("print('python end')");
    
    	////  python
    	Py_Finalize();
    
    	system("pause");
    	return 0;
    }
    
  • です.