caffe2 ios 배포

1. caffe2 ios 프로젝트 컴파일 설정


커피2의 ios 컴파일링 및 배치에 관하여github에 비교적 성숙한 코드가 있으니 이 작가의 업무를 바탕으로 수정 배치를 선택하십시오.https://github.com/KleinYuan/Caffe2-iOS저자가 제시한 절차에 따라git clone과 컴파일을 진행합니다
brew install git-lfs
git lfs install
git lfs clone https://github.com/KleinYuan/Caffe2-iOS

완성 후 src 디렉터리에 들어가서 setup을 호출합니다.sh, 자동으로 카페2를 다운로드하고 카페2의 OS 라이브러리를 컴파일합니다
cd Caffe2-iOS/src/caffe2-ios
bash ./setup.sh

지난 단계는 대략 20~30분 정도 걸렸다.완성되면 src 디렉터리에 커피2 디렉터리가 새로 만들어집니다. 커피2 원본 파일과 컴파일된 라이브러리가 포함되어 있습니다.저자는 이미 프로젝트에 모든 것을 설정했기 때문에 xcode 프로젝트를 열어 테스트만 하면 됩니다.src/caffe2-ios/caffe2-ios를 엽니다.xcodeproj를 컴파일합니다. 여기 오류가 발생했습니다. 힌트caffe2.pb.h 및 predictorconsts.pb.h못 찾겠어요.위의 설치 과정이 정상적이라면 src/caffe2/caffe2/caffe2/proto 경로에서 protobuf의protoc를 호출하여 생성할 것입니다. 그러나 제 위의 설치 과정에서 이 단계를 건너뛰었습니다. 괜찮습니다. 수동으로 생성할 수 있습니다.시스템에 protobuf가 설치되어 있든 없든 src/caffe2/buildhost_protoc/bin에서 protoc를 생성합니다. 그렇지 않으면 버전이 일치하지 않는 오류가 발생할 수 있습니다.
cd src/caffe2/caffe2/proto
../../build_host_protoc/bin/protoc caffe2.proto --cpp_out=./
../../build_host_protoc/bin/protoc predictor_consts.proto --cpp_out=./

생성된 후 xcode 프로젝트를 다시 컴파일하면 컴파일에 성공하면 실행할 수 있습니다.demo에서 저자는 두 개의 카페2 모델을 제시했다. squeezenet과tinyyolo이다. 내가 아이폰6sp에서 측정한 시간은 각각 35ms/frame와 52ms/frame이다.

2. 자신의 카페 모델을 전환하고 ios에 배치


2.1 설치 커피2 컴파일


이전 단계에서 저자가 제시한 카페2 모델을 테스트했지만, 자신의 카페 모델을 OS에 배치하려면?커피2는 변환된 인터페이스를 편리하게 제공합니다. 이 인터페이스를 사용하기 전에 커피2를 설치하고 설치한 iOS 라이브러리를 컴파일해야 합니다. 커피2 디렉터리에 들어가서build 폴더를 새로 만들어야 합니다.
cd src/caffe2
mkdir build && cd build
cmake -DUSE_CUDA=OFF ..
sudo make install

설치가 성공하면 커피2와 관련된 라이브러리와python 라이브러리는/usr/local에 설치됩니다. 물론 cmake에서 설치 디렉터리를 지정하여python 환경 변수에/usr/local을 추가할 수 있습니다.
export PYTHONPATH=/usr/local

완성되면 오류가 있는지 테스트를 해볼 수 있어요.
cd ~ && python -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"

2.2 커피모델을 커피2모델로 변환


python 인터페이스 caffe 호출translator 변환 카페2 모형
python caffe2/python/caffe_translator.py deploy.prototxt test_iter_83000.caffemodel --init_net=testinit.pb --predict_net=testpredict.pb

최종적으로 필요한 것은 변환된 모델testinit이다.pb와testpredict.pb

2.3 ios에 카페2 모델 적용


프로젝트에 변환된 모델 성명caffe2 대상을 추가하고
@property (nonatomic, strong) Caffe2 *caffe2;
self.caffe2 = [[Caffe2 alloc] init:@"init" predict:@"predict" error:&err];

이미지 예측
NSMutableArray *ret = [self.caffe2 predictwithmat:resimg withMean: &mean_val withScale:1.f];

여기의predict 인터페이스 함수는 자체적으로 실현된 것으로 오픈cv 이미지와 균일치 감소와 귀일화 등 사전 처리를 입력할 수 있습니다
- (nullable NSArray*) predictwithmat:(cv::Mat) image withMean: (float*)mean_val withScale: (float) scale
{
    NSMutableArray* result = nil;
    caffe2::Predictor::TensorVector output_vec;

    if (self.busyWithInference) {
        return nil;
    } else {
        self.busyWithInference = true;
    }

    UInt8* pixels = (UInt8*) image.data;
    caffe2::TensorCPU input;
    size_t  w = image.cols, h = image.rows ;
    // Reasonable dimensions to feed the predictor.
    const int predHeight = (int)CGSizeEqualToSize(self.imageInputDimensions, CGSizeZero) ? int(h) : self.imageInputDimensions.height;
    const int predWidth = (int)CGSizeEqualToSize(self.imageInputDimensions, CGSizeZero) ? int(w) : self.imageInputDimensions.width;
    const int crops = 1;
    const int channels = image.channels();
    const int size = predHeight * predWidth;

    std::vector<float> inputPlanar(crops * channels * predHeight * predWidth);

    if (channels > 1) //bgr img
    {
        for (int c = 0; c < channels; c++)
        {
            for (int i = 0; i < predHeight; i++)
            {
                for (int j = 0; j < predWidth; j++)
                {
                    inputPlanar[i * predWidth + j + c * size] = scale * float(image.at<:vec3b>(i, j)[c] - mean_val[c]);
                }
            }
        }
    }
    else{
        for (int i = 0; i < predHeight; i++)
        {
            for (int j = 0; j < predWidth; j++)
            {
                inputPlanar[i * predWidth + j ] = scale * float(image.at(i, j) - mean_val[0]);
            }
        }

    }

    input.Resize(std::vector<int>({crops, channels, predHeight, predWidth}));
    input.ShareExternalPointer(inputPlanar.data());

    caffe2::Predictor::TensorVector input_vec{&input};
    NSTimeInterval start = [[NSDate date] timeIntervalSince1970];
    _predictor->run(input_vec, &output_vec);
    NSTimeInterval end = [[NSDate date] timeIntervalSince1970];

    NSLog(@"elapsed time %f" , (end-start)*1000);
    if (output_vec.capacity() > 0) {
        for (auto output : output_vec) {
            // currently only one dimensional output supported
            result = [NSMutableArray arrayWithCapacity:output_vec.size()];
            for (auto i = 0; i < output->size(); ++i) {
                result[i] = @(output->template data<float>()[i]);
                NSLog(@"%@", result[i]);
            }
        }
    }

    self.busyWithInference = false;
    return result;
}

좋은 웹페이지 즐겨찾기