【发布时间】:2011-11-13 16:14:44
【问题描述】:
我正在尝试在 OpenCV 中编写一个程序来将图像转换为矩阵形式,每个值代表图像的像素。我已将图像转换为二进制形式,现在我想将其像素值转换为矩阵。
【问题讨论】:
-
您应该做的第一件事是添加一个代码示例,说明您目前已经获得了什么以及您想要什么。
-
我已经添加了它并进一步解释。
标签: c++ visual-c++ opencv
我正在尝试在 OpenCV 中编写一个程序来将图像转换为矩阵形式,每个值代表图像的像素。我已将图像转换为二进制形式,现在我想将其像素值转换为矩阵。
【问题讨论】:
标签: c++ visual-c++ opencv
乍一看您的问题会引发更多问题...尝试指定一点(我似乎无法看到您的代码示例,我是stackoverflow的新手) 例如,您打开的 cv 版本和 IDE(如代码块或 Microsoft Visual Studio)。但将其包含在您的问题中。我还想知道,这样做的目的是什么?为什么你需要一个矩阵等等:)
尝试回答
据我所知 “但我已经在 Visual C++ 2010 上安装了 OpenCV 2.3.1 版 – Ayesha Khan”
OpenCV 使用名为 Mat 的类,你应该经常遇到。这个类本质上已经是一个矩阵了。如果我没记错的话,它与向量非常相似,我不会在这里介绍。
因此,如果您需要访问其中的任何像素值,可以说。
Mat Img;
你会在这个类的实例中使用一个函数,就像这样
cout << Img.at<uchar>(x,y);
这将访问并打印坐标为 x,y 的像素值到控制台。在这个例子中,我在尖括号 中使用了 uchar。 uchar 用于 8 位图片。如果您使用更详细(更多位)的图像,则必须更改此设置。
当使用二进制图片时,OpenCV 很可能会分配 8bit 的内存,也就是说你需要上面的例子。
我想提供更多详细信息,但在您明确说明您正在尝试做什么之前。
问候 Scrub @ Stackoverflow
【讨论】:
您的代码使用 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;
}
}
【讨论】: