Как связать библиотеку libsvm в google colab при выполнении CUDA? Каков правильный флаг связывания для libsvm? - PullRequest
0 голосов
/ 25 января 2020

Я работаю над Google Colab и хочу использовать библиотеку libsvm в своем проекте. Я скачал libsvm и установил его. Теперь, когда я использую команду! Nv cc -o и запускаю код, используя CUDA, я получаю ошибки вроде:

undefined reference to `svm_get_nr_class
undefined reference to 'svm_predict_probability'
undefined reference to `svm_free_and_destroy_model

Полагаю, проблема в том, что libsvm неправильно связан, так как я использую -l с соответствующими флагами для компиляции с nv cc, но я не знаю, что использовать с -l чтобы правильно связать libsvm и использовать его.

я скачал libsvm, используя

!git clone https://github.com/cjlin1/libsvm
%cd libsvm/
!make && make install
%cd /content/libsvm/python/
!make
import sys
sys.path.append('/content/libsvm/python')
%cd /content

теперь, когда я запускаю эту программу

%%cuda --name Blind_Deblurring_Cuda.cu
#include <iostream>
#include <fstream>
#include <iostream>
#include <fstream>
#include "/content/brisque.h"
#include "/content/libsvm/svm.h"


#include <vector>
#include <stdio.h>
#include "fstream"
#include "iostream"
#include <algorithm>
#include <iterator>
#include <cmath>
#include<stdlib.h>              
#include <math.h>
#include <curand.h>
#include <opencv2/core/cuda.hpp>

#include <opencv2/core.hpp>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include <opencv2/core/core.hpp>
#include <iostream>
#include "opencv2/highgui.hpp"
#include <opencv2/core/utility.hpp>


//rescaling based on training data i libsvm
float rescale_vector[36][2];

using namespace std;
using namespace cv;

float computescore(string imagename);
void ComputeBrisqueFeature(Mat& orig, vector<double>& featurevector);

int read_range_file() {
  //check if file exists
  char buff[100];
  int i;
  string range_fname = "allrange";
  FILE* range_file = fopen(range_fname.c_str(), "r");
  if(range_file == NULL) return 1;
  //assume standard file format for this program    
  fgets(buff, 100, range_file);
  fgets(buff, 100, range_file);
  //now we can fill the array
  for(i = 0; i < 36; ++i) {
    float a, b, c; 
    fscanf(range_file, "%f %f %f", &a, &b, &c);
    rescale_vector[i][0] = b;
    rescale_vector[i][1] = c;
  }
  return 0; 
}


int main(int argc, char** argv)
{   
  if(argc < 2) {
    cout << "Input Image argument not given." << endl;
   return -1;
  }

  //read in the allrange file to setup internal scaling array
  if(read_range_file()) {
    cerr<<"unable to open allrange file"<<endl;
    return -1;
  }

  float qualityscore;
  qualityscore = computescore(argv[1]);
  cout << "Quality Score: " << qualityscore << endl;
}


float computescore(string imagename) {
  // pre-loaded vectors from allrange file 
  float min_[36] = {0.336999 ,0.019667 ,0.230000 ,-0.125959 ,0.000167 ,0.000616 ,0.231000 ,-0.125873 ,0.000165 ,0.000600 ,0.241000 ,-0.128814 ,0.000179 ,0.000386 ,0.243000 ,-0.133080 ,0.000182 ,0.000421 ,0.436998 ,0.016929 ,0.247000 ,-0.200231 ,0.000104 ,0.000834 ,0.257000 ,-0.200017 ,0.000112 ,0.000876 ,0.257000 ,-0.155072 ,0.000112 ,0.000356 ,0.258000 ,-0.154374 ,0.000117 ,0.000351};

  float max_[36] = {9.999411, 0.807472, 1.644021, 0.202917, 0.712384, 0.468672, 1.644021, 0.169548, 0.713132, 0.467896, 1.553016, 0.101368, 0.687324, 0.533087, 1.554016, 0.101000, 0.689177, 0.533133, 3.639918, 0.800955, 1.096995, 0.175286, 0.755547, 0.399270, 1.095995, 0.155928, 0.751488, 0.402398, 1.041992, 0.093209, 0.623516, 0.532925, 1.042992, 0.093714, 0.621958, 0.534484};

  double qualityscore;
  int i;
  struct svm_model* model; // create svm model object
  Mat orig = imread(imagename, 1); // read image (color mode)

  vector<double> brisqueFeatures; // feature vector initialization
  ComputeBrisqueFeature(orig, brisqueFeatures); // compute brisque features

  // use the pre-trained allmodel file

  string modelfile = "allmodel";
  //if((model=svm_load_model(modelfile.c_str()))==0) {
    //fprintf(stderr,"can't open model file allmodel\n");
//    exit(1);
  //}

  // float min_[37];
  // float max_[37];

  struct svm_node x[37];
  // rescale the brisqueFeatures vector from -1 to 1 
  // also convert vector to svm node array object
  for(i = 0; i < 36; ++i) {
    float min = min_[i];
    float max = max_[i];

    x[i].value = -1 + (2.0/(max - min) * (brisqueFeatures[i] - min));
    x[i].index = i + 1;
  }
  x[36].index = -1;


  int nr_class=svm_get_nr_class(model);
  double *prob_estimates = (double *) malloc(nr_class*sizeof(double));
  // predict quality score using libsvm class
  qualityscore = svm_predict_probability(model,x,prob_estimates);

  free(prob_estimates);
  svm_free_and_destroy_model(&model);
  return qualityscore;
}
void ComputeBrisqueFeature(Mat& orig, vector<double>& featurevector)
{
  Mat orig_bw_int(orig.size(), CV_64F, 1); 
  // convert to grayscale 
  cvtColor(orig, orig_bw_int, COLOR_BGR2GRAY);
  // create a copy of original image
  Mat orig_bw(orig_bw_int.size(), CV_64FC1, 1);
  orig_bw_int.convertTo(orig_bw, 1.0/255);
  orig_bw_int.release();

  // orig_bw now contains the grayscale image normalized to the range 0,1

  int scalenum = 2; // number of times to scale the image
  for (int itr_scale = 1; itr_scale<=scalenum; itr_scale++)
  {
    // resize image
    Size dst_size(orig_bw.cols/cv::pow((double)2, itr_scale-1), orig_bw.rows/pow((double)2, itr_scale-1));
    Mat imdist_scaled; 
    resize(orig_bw, imdist_scaled, dst_size, 0, 0, INTER_CUBIC); // INTER_CUBIC
    imdist_scaled.convertTo(imdist_scaled, CV_64FC1, 1.0/255.0);
    // calculating MSCN coefficients
    // compute mu (local mean)
    Mat mu(imdist_scaled.size(), CV_64FC1, 1);
    GaussianBlur(imdist_scaled, mu, Size(7, 7), 1.166);

    Mat mu_sq;
    cv::pow(mu, double(2.0), mu_sq);

    //compute sigma (local sigma)
    Mat sigma(imdist_scaled.size(), CV_64FC1, 1);
    cv::multiply(imdist_scaled, imdist_scaled, sigma);
    GaussianBlur(sigma, sigma, Size(7, 7), 1.166);

    cv::subtract(sigma, mu_sq, sigma);
    cv::pow(sigma, double(0.5), sigma);
    add(sigma, Scalar(1.0/255), sigma); // to avoid DivideByZero Error

    Mat structdis(imdist_scaled.size(), CV_64FC1, 1);
    subtract(imdist_scaled, mu, structdis);
    divide(structdis, sigma, structdis);  // structdis is MSCN image

    // Compute AGGD fit to MSCN image
    double lsigma_best, rsigma_best, gamma_best;

    structdis = AGGDfit(structdis, lsigma_best, rsigma_best, gamma_best);
    featurevector.push_back(gamma_best);
    featurevector.push_back((lsigma_best*lsigma_best + rsigma_best*rsigma_best)/2);

    // Compute paired product images
    // indices for orientations (H, V, D1, D2)
    int shifts[4][2]={{0,1},{1,0},{1,1},{-1,1}};

    for(int itr_shift=1; itr_shift<=4; itr_shift++)
    {
      // select the shifting index from the 2D array
      int* reqshift = shifts[itr_shift-1];

      // declare shifted_structdis as pairwise image
      Mat shifted_structdis(imdist_scaled.size(), CV_64F, 1);

      // create copies of the images using BwImage constructor
      // utility constructor for better subscript access (for pixels)
      BwImage OrigArr(structdis);
      BwImage ShiftArr(shifted_structdis);

      // create pair-wise product for the given orientation (reqshift)
      for(int i=0; i<structdis.rows; i++)
      {
        for(int j=0; j<structdis.cols; j++)
        {
          if(i+reqshift[0]>=0 && i+reqshift[0]<structdis.rows && j+reqshift[1]>=0 && j+reqshift[1]<structdis.cols)
          {
            ShiftArr[i][j]=OrigArr[i + reqshift[0]][j + reqshift[1]];
          }
          else
          {
            ShiftArr[i][j]=0;
          }
        }
      }

      // Mat structdis_pairwise;
      shifted_structdis = ShiftArr.equate(shifted_structdis);

      // calculate the products of the pairs
      multiply(structdis, shifted_structdis, shifted_structdis);

      // fit the pairwise product to AGGD 
      shifted_structdis = AGGDfit(shifted_structdis, lsigma_best, rsigma_best, gamma_best);

      double constant = sqrt(tgamma(1/gamma_best))/sqrt(tgamma(3/gamma_best));
      double meanparam = (rsigma_best-lsigma_best)*(tgamma(2/gamma_best)/tgamma(1/gamma_best))*constant;

      // push the calculated parameters from AGGD fit to pair-wise products
      featurevector.push_back(gamma_best);
      featurevector.push_back(meanparam);
      featurevector.push_back(cv::pow(lsigma_best,2));
      featurevector.push_back(cv::pow(rsigma_best,2));  
    }
  }
}

// function to compute best fit parameters from AGGDfit 
Mat AGGDfit(Mat structdis, double& lsigma_best, double& rsigma_best, double& gamma_best)
{
  // create a copy of an image using BwImage constructor (brisque.h - more info)
  BwImage ImArr(structdis);

  long int poscount=0, negcount=0;
  double possqsum=0, negsqsum=0, abssum=0;
  for(int i=0;i<structdis.rows;i++)
  {
    for (int j =0; j<structdis.cols; j++)
    {
      double pt = ImArr[i][j]; // BwImage provides [][] access
      if(pt>0)
      {
        poscount++;
        possqsum += pt*pt; 
        abssum += pt;
      }
      else if(pt<0)
      {
        negcount++;
        negsqsum += pt*pt;
        abssum -= pt;
      }
    }
  }

  lsigma_best = cv::pow(negsqsum/negcount, 0.5);
  rsigma_best = cv::pow(possqsum/poscount, 0.5);

  double gammahat = lsigma_best/rsigma_best;
  long int totalcount = (structdis.cols)*(structdis.rows);
  double rhat = cv::pow(abssum/totalcount, static_cast<double>(2))/((negsqsum + possqsum)/totalcount);
  double rhatnorm = rhat*(cv::pow(gammahat,3) +1)*(gammahat+1)/pow(pow(gammahat,2)+1,2);

  double prevgamma = 0;
  double prevdiff = 1e10;   
  float sampling = 0.001;
  for (float gam=0.2; gam<10; gam+=sampling) //possible to coarsen sampling to quicken the code, with some loss of accuracy
  {
    double r_gam = tgamma(2/gam)*tgamma(2/gam)/(tgamma(1/gam)*tgamma(3/gam));
    double diff = abs(r_gam-rhatnorm);
    if(diff> prevdiff) break;
    prevdiff = diff;
    prevgamma = gam;
  }
  gamma_best = prevgamma;

  return structdis.clone();
}

А затем попробуйте скомпилировать, используя

!nvcc -o /content/src/Blind_Deblurring_Cuda /content/src/Blind_Deblurring_Cuda.cu  -lopencv_core -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_ml

выдает следующую ошибку

/tmp/tmpxft_00003d8d_00000000-10_Blind_Deblurring_Cuda.o: In function `computescore(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
tmpxft_00003d8d_00000000-5_Blind_Deblurring_Cuda.cudafe1.cpp:(.text+0x9bc): undefined reference to `svm_get_nr_class'
tmpxft_00003d8d_00000000-5_Blind_Deblurring_Cuda.cudafe1.cpp:(.text+0x9fd): undefined reference to `svm_predict_probability'
tmpxft_00003d8d_00000000-5_Blind_Deblurring_Cuda.cudafe1.cpp:(.text+0xa27): undefined reference to `svm_free_and_destroy_model'
collect2: error: ld returned 1 exit status
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...