Как конвертировать изображение в матрицу с помощью OpenCV? - PullRequest
1 голос
/ 13 ноября 2011

Я пытаюсь создать программу в OpenCV для преобразования изображения в матричную форму, где каждое значение представляет пиксель изображения. Я преобразовал изображение в двоичную форму и теперь хочу преобразовать его значения пикселей в матрицу.

Ответы [ 3 ]

1 голос
/ 14 ноября 2011

Если вам нужно использовать объект CvMat, вы можете попробовать использовать функцию cvCopy . В качестве аргументов он принимает CvArr *, поэтому подойдут как IPLImage, так и CvMat. Если Вы оставите C API и перейдете к чему-то более современному, Вы можете использовать объект cv :: Mat для загрузки изображения и использования C ++ threshold .

Вопрос в том, почему вы хотите преобразовать формат матрицы, который у вас уже есть (IPLImage, как и все остальные, уже являются матрицами). Если вы хотите иметь матрицу типа bool, используйте для этого Matx или Mat_ шаблонный класс.

1 голос
/ 16 ноября 2011

При первом взгляде на ваш вопрос возникает больше вопросов ... попробуйте указать немного (мне кажется, я не вижу вашего кода, я новичок в stackoverflow) Например, версия open cv и IDE (например, кодовые блоки или Microsoft Visual Studio). Но включите это в свой вопрос. Что я также хотел бы знать, какова цель этого? Зачем тебе матрица и прочее:)

попытка ответа

из того, что я могу собрать «но я установил OpenCV версии 2.3.1 на Visual C ++ 2010 - Айеша Хан»

OpenCV использует класс с именем Mat, с которым вам часто приходилось сталкиваться. Этот класс по сути уже является матрицей. Если я правильно помню, это очень похоже на векторы, которые я не буду здесь описывать.

так что если вам нужно получить доступ к какому-либо значению пикселя, скажем так.

Mat Img;

вы бы использовали функцию в этом экземпляре класса, как таковую

cout << Img.at<uchar>(x,y);

Это откроет и выведет значение пикселя с координатами x, y на консоль. В этом примере я использую uchar внутри заостренных скобок <>. Учар используется для 8-битных картинок. Вам придется изменить это, если вы работаете с изображениями более подробно (больше битов).

При использовании двоичного изображения OpenCV, скорее всего, выделит 8-битную память, что означает, что вам нужен приведенный выше пример.

Я хотел бы дать больше подробностей, но не раньше, чем вы укажете, что именно вы пытаетесь сделать.

С уважением, Скраб @ Stackoverflow

0 голосов
/ 13 ноября 2011

Ваш код использует OpenCV версии 1. Я позволю кому-то другому ответить, поскольку это не моя сильная сторона.На мой взгляд, интерфейс на основе шаблонов 2.0 гораздо более интуитивен, и я рекомендую использовать его для всех новых начинаний.

Посмотрите, как я использую imread () в этой программе ...Пожалуйста, проверьте тип значения, возвращаемого из imread () ... Кроме того, поиск в коде для originalColor = imageArg(/*row*/chosenX, /*column*/chosenY); Это способ индексации в матрице, возвращенной из imread

// HW1 Intro to Digital Image Processing 
// used OpenCV 2.3.1 and VS2010 SP1 to develop this solution

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <cassert>

using namespace cv;

Mat_<Vec3b> image;
int discreteAngles = 512;

void on_mouse(int eventCode, int centerX, int centerY, int flags, void* params);
int str2int(const std::string &str);

int main(int argc, char* argv[])
{
   // command itself is one element of argument array...
   if(argc != 1 && argc != 3)
   {
      std::cout << "Expecting two arguments to the application: angular granularity as a whole number and a file name." << std::endl;
      exit(0);
   }

   std::string discreteAnglesStr, fileName;

   if(argc == 3)
   {
      discreteAnglesStr = argv[1];
      fileName          = argv[2];
   }
   else
   {
      discreteAnglesStr = "64";
      fileName          = "boats.tif";
   }

   try
   {
      discreteAngles = str2int(discreteAnglesStr);
      auto image_ = imread(fileName);
      int channels = image_.channels();
      assert(channels == 3);
      image = image_;

      if(image.rows == 0)
         throw new std::exception();

      auto originalImageStr = "Original Image";
      namedWindow(originalImageStr);
      setMouseCallback(originalImageStr, on_mouse);
      imshow(originalImageStr, image);
   }
   catch(std::exception e)
   {
      std::cout << "could not load image." << std::endl;
   }
   waitKey(0);
   return -1;
}

// borrowed from http://stackoverflow.com/q/194465/90475, courtesy of Luka Marinko
int str2int(const std::string &str)
{
   std::stringstream ss(str);
   int num;
   if((ss >> num).fail())
   { 
      throw new std::exception("could not parse user input!");
   }
   return num;
}

double compute_max_madius(int imageRows, int imageCols, int centerX, int centerY)
{
   auto otherX = imageCols - centerX;
   auto otherY = imageRows - centerY;

   auto a = sqrt((double)centerX * centerX + centerY * centerY);
   auto b = sqrt((double)otherX * otherX + centerY * centerY);
   auto c = sqrt((double)centerX * centerX + otherY * otherY);
   auto d = sqrt((double)otherX * otherX + otherY * otherY);

   return max(max(a,b), max(c,d));
}

Vec3b interpolate_with_nearest(const Mat_<Vec3b>& imageArg, double x, double y)
{
   auto x0 = static_cast<int>(floor(x)); auto y0 = static_cast<int>(floor(y));
   auto x1 = static_cast<int>(ceil(x));  auto y1 = static_cast<int>(ceil(y));

   // Rolls over to the other side, esp. for angles
   if(x0 < 0) x0 = imageArg.rows - 1;
   if(y0 < 0) y0 = imageArg.cols - 1;

   if (x1 == imageArg.rows) x1 = 0;
   if (y1 == imageArg.cols) y1 = 0;

   int chosenX, chosenY;
   if (x - x0 < 0.5) chosenX = x0; else chosenX = x1;
   if (y - y0 < 0.5) chosenY = y0; else chosenY = y1;

   Vec3b originalColor = Vec3b(0, 0, 0);
   if (chosenX >= 0 && chosenX < imageArg.rows &&
      chosenY >= 0 && chosenY < imageArg.cols)
   {
      originalColor = imageArg(/*row*/chosenX, /*column*/chosenY);
   }

   return originalColor;
}

Vec3b interpolate_with_bilinear(const Mat_<Vec3b>& imageArg, double x, double y)
{
   auto x0 = static_cast<int>(floor(x)); auto y0 = static_cast<int>(floor(y));
   auto x1 = static_cast<int>(ceil(x));  auto y1 = static_cast<int>(ceil(y));

   // Rolls over to the other side, esp. for angles
   if(x0 < 0) x0 = imageArg.rows - 1;
   if(y0 < 0) y0 = imageArg.cols - 1;

   if (x1 == imageArg.rows) x1 = 0;
   if (y1 == imageArg.cols) y1 = 0;

   if (!(
      x0 >= 0 && x0 < imageArg.rows &&
      x1 >= 0 && x1 < imageArg.rows &&
      y0 >= 0 && y0 < imageArg.cols &&
      y1 >= 0 && y1 < imageArg.cols))
      return Vec3b(0, 0, 0);

   auto f00 = imageArg(x0, y0);
   auto f01 = imageArg(x0, y1);
   auto f10 = imageArg(x1, y0);
   auto f11 = imageArg(x1, y1);

   auto b1 = f00;
   auto b2 = f10 - f00;
   auto b3 = f01 - f00;
   auto b4 = f00 + f11 - f01 - f10;

   x = x - x0;
   y = y - y0;

   return b1 + b2 * x + b3 * y + b4 * x * y;
}

void on_mouse(int eventCode, int centerX, int centerY, int flags, void* params)
{
   if(eventCode == 0)
      return;

   switch( eventCode )
   {
   case CV_EVENT_LBUTTONDOWN:
      {
         std::cout << "Center was (" << centerX << ", " << centerY << ")" << std::endl;

         auto maxRadiusXY = compute_max_madius(image.rows, image.cols, centerX, centerY);
         int discreteRadii = static_cast<int>(floor(maxRadiusXY));

         Mat_<Vec3b> polarImg1;
         polarImg1.create(/*rows*/discreteRadii, /*cols*/discreteAngles);

         Mat_<Vec3b> polarImg2;
         polarImg2.create(/*rows*/discreteRadii, /*cols*/discreteAngles);

         for (int radius = 0; radius < discreteRadii; radius++) // radii
         {
            for (int discreteAngle = 0; discreteAngle < discreteAngles; discreteAngle++) // discreteAngles
            {
               // 3
               auto angleRad = discreteAngle * 2.0 * CV_PI / discreteAngles;

               // 2
               auto xTranslated = cos(angleRad) * radius;
               auto yTranslated = sin(angleRad) * radius;

               // 1
               auto x = centerX + xTranslated;
               auto y = centerY - yTranslated;

               polarImg1(/*row*/ radius, /*column*/ discreteAngle) = interpolate_with_nearest(image, /*row*/y, /*column*/x);
               polarImg2(/*row*/ radius, /*column*/ discreteAngle) = interpolate_with_bilinear(image, /*row*/y, /*column*/x);
            }
         }

         auto polarImage1Str = "Polar (nearest)";
         namedWindow(polarImage1Str);
         imshow(polarImage1Str, polarImg1);

         auto polarImage2Str = "Polar (bilinear)";
         namedWindow(polarImage2Str);
         imshow(polarImage2Str, polarImg2);

         Mat_<Vec3b> reprocessedImg1;
         reprocessedImg1.create(Size(image.rows, image.cols));

         Mat_<Vec3b> reprocessedImg2;
         reprocessedImg2.create(Size(image.rows, image.cols));

         for(int y = 0; y < image.rows; y++)
         {
            for(int x = 0; x < image.cols; x++)
            {
               // 1
               auto xTranslated = x - centerX;
               auto yTranslated = -(y - centerY);

               // 2
               auto radius = sqrt((double)xTranslated * xTranslated + yTranslated * yTranslated);

               double angleRad;
               if(xTranslated != 0)
               {
                  angleRad = atan((double)abs(yTranslated) / abs(xTranslated));

                  // I Quadrant
                  if (xTranslated > 0 && yTranslated > 0)
                     angleRad = angleRad;
                  // II Quadrant
                  if (xTranslated < 0 && yTranslated > 0)
                     angleRad = CV_PI - angleRad;
                  // III Quadrant
                  if (xTranslated < 0 && yTranslated < 0)
                     angleRad = CV_PI + angleRad;
                  /// IV Quadrant
                  if (xTranslated > 0 && yTranslated < 0)
                     angleRad = 2 * CV_PI - angleRad;

                  if (yTranslated == 0)
                     if (xTranslated > 0) angleRad = 0;
                     else angleRad = CV_PI;
               }
               else
               {
                  if (yTranslated > 0) angleRad = CV_PI / 2;
                  else angleRad = 3 * CV_PI / 2;
               }

               // 3
               auto discreteAngle = angleRad * discreteAngles / (2.0 * CV_PI);

               reprocessedImg1(/*row*/ y, /*column*/ x) = interpolate_with_nearest(polarImg1, /*row*/radius, /*column*/discreteAngle);
               reprocessedImg2(/*row*/ y, /*column*/ x) = interpolate_with_bilinear(polarImg2, /*row*/radius, /*column*/discreteAngle);
            }
         }

         auto reprocessedImg1Str = "Re-processed (nearest)";
         namedWindow(reprocessedImg1Str);
         imshow(reprocessedImg1Str, reprocessedImg1);

         auto reprocessedImg2Str = "Re-processed (bilinear)";
         namedWindow(reprocessedImg2Str);
         imshow(reprocessedImg2Str, reprocessedImg2);

      } break;
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...