Ayesha Khan
Ayesha Khan

Reputation: 155

how to convert image in to matrix using opencv?

I am trying to make a program in OpenCV to convert an image into matrix form, with each value representing an image's pixel. I have converted the image into binary form and now I want to convert it's pixel values into a matrix.

Upvotes: 1

Views: 8139

Answers (3)

Sonaten
Sonaten

Reputation: 502

First glance at your question raises more questions... try to specify a bit (I don't seem to be able to see your code example, I'm new to stackoverflow) Such as, your open cv version and IDE (like codeblocks or Microsoft Visual Studio). But include it in your question. What I would also like to know, is what is the purpose of this? Why do you need a matrix and so forth :)

attempted answer

from what I can gather "but I have installed OpenCV version 2.3.1 on Visual C++ 2010 – Ayesha Khan"

OpenCV uses the class called Mat, which you should have encountered a lot. This class is essentially a matrix already. If I remember correctly it is very similar to vectors, which I won't cover here.

so if you need to access any pixel value in, lets say.

Mat Img;

you would use a function in this instance of the class, as such

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

This will access and print the value of the pixel with the coordinates of x,y, to console. In this example I use uchar inside the pointy brackets <>. uchar is used for 8bit picures. You will have to change this if you work with images of more detail (more bits).

When using a binary picture, OpenCV will most likely will allocate the memory of 8bit, which means you need the example above.

I'd like to give more details, but not before you've specified what exactly it is that you are attempting to do.

Regards Scrub @ Stackoverflow

Upvotes: 1

morynicz
morynicz

Reputation: 2332

If You need to use CvMat object, You may want to try to use cvCopy function. It takes CvArr* as its arguments, so both IPLImage and CvMat will fit. If You would leave the C API and go to something more modern, You can use cv::Mat object to load image into and use C++ threshold.

The question is why do You want to convert the format of matrix that you already have (IPLImage as well as all others are matrices already). If You want to have a matrix of bool type, use Matx or Mat_ template class for this.

Upvotes: 1

GregC
GregC

Reputation: 7977

Your code uses OpenCV version 1. I'll let someone else answer, since it's not my forte. In my opinion, the 2.0 template-based interface is much more intuitive, and it's my recommendation to use it for all new endeavors.

Have a look at the way I use imread() in this program... Please inspect the type of value returned from imread()... Also, search in the code for originalColor = imageArg(/*row*/chosenX, /*column*/chosenY); It's a way to index into the matrix returned from 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;
   }
}

Upvotes: 0

Related Questions