C++ 我不知道';我不明白为什么我的c++;代码运行得太慢了
我正在研究用于边缘检测的Sobel掩蔽,无需使用任何特殊库。我想要得到的输出是一个带有512x512矩阵的文本文件,其值介于0到1之间。 我检查了代码是否正常工作,将较小的值(如50)替换为“ROW-2”和“COL-2”。 然而,如果我把它们放回原处,代码将永远无法运行 常量值为:C++ 我不知道';我不明白为什么我的c++;代码运行得太慢了,c++,performance,edge-detection,sobel,C++,Performance,Edge Detection,Sobel,我正在研究用于边缘检测的Sobel掩蔽,无需使用任何特殊库。我想要得到的输出是一个带有512x512矩阵的文本文件,其值介于0到1之间。 我检查了代码是否正常工作,将较小的值(如50)替换为“ROW-2”和“COL-2”。 然而,如果我把它们放回原处,代码将永远无法运行 常量值为: const int ROW = 512; const int COL = 512; const double Gx [3][3] = { {-1.0,0.0,1.0},{-2.0,0.0,2.0},{-1.0,0.0
const int ROW = 512;
const int COL = 512;
const double Gx [3][3] = { {-1.0,0.0,1.0},{-2.0,0.0,2.0},{-1.0,0.0,1.0}};
const double Gy [3][3] = { {1.0,2.0,1.0},{0.0,0.0,0.0},{-1.0,-2.0,-1.0}};
这是主要功能:
int main()
{
double NewImage[ROW][COL] = {0};
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
NewImage[i][j] = 0;
}
}
for (int i = 0; i < ROW-2; i++)
{
for (int j = 0; j < COL-2; j++)
{
NewImage[i+1][j+1] = SobelConvolution(i,j);
}
}
ofstream newImage;
string filename;
filename = "output image.txt";
newImage.open (filename.c_str());
for(int rows = 0; rows < ROW; rows++)
{
for(int cols = 0; cols < COL; cols++)
{
newImage << NewImage[ROW][COL] <<" ";
}
newImage << endl;
}
newImage.close();
return 0;
}
这是ImageReader的功能:
double ImageReader(int r, int c)
{
double OrigImage[ROW][COL];
ifstream defaultImage ("image.txt");
if (defaultImage.good())
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
defaultImage >> OrigImage[i][j];
}
}
}
return OrigImage [r][c];
}
双图像阅读器(int r,int c)
{
双原点[行][列];
ifstreamdefaultimage(“image.txt”);
if(defaultImage.good())
{
对于(int i=0;i>原始图像[i][j];
}
}
}
返回原图像[r][c];
}
有什么提示或建议吗?提前谢谢 您真的想打开单个图像文件18次,读取每行和每列的所有数据,只返回单个行和列18次吗?为什么不读取一次图像文件并将图像数据数组传递给函数?以下是一些注意事项:
只返回数组的一个值,无需每次只需要一个值就读取整个数组。我认为这个功能是多余的图像阅读器
此函数很好,但有一个不必要的变量-sobelcolution
conv
我不知道为什么您要将main
的每个值初始化为NewImage
,而它们已经是0
!您实际上也不需要0
NewImage
双Sobel卷积(int行,int列)
{
//ImageReader已被删除,这是不必要的。代码已移到此处
双旧图像[行][列];
std::ifstreamdefaultimage{“image.txt”};
//错误处理如果文件不存在-考虑做其他事情:
如果(!defaultImage.is_open())
返回0;
//初始化数组
对于(int i=0;i>oldImage[i][j];
//您应该始终在第一次使用变量的位置声明变量,如下所示
//减少出错的可能性
//我们可以直接访问阵列
双convX=oldImage[行][col]*Gx[2][2]
+oldImage[行][col+1]*Gx[2][1]
+oldImage[row][col+2]*Gx[2][0]
+oldImage[行+1][col]*Gx[1][2]
+oldImage[行+1][列+1]*Gx[1][1]
+oldImage[row+1][col+2]*Gx[1][0]
+oldImage[row+2][col]*Gx[0][2]
+oldImage[row+2][col+1]*Gx[0][1]
+oldImage[row+2][col+2]*Gx[0][0];
双通道=旧图像[行][col]*Gy[2][2]
+旧图像[行][col+1]*Gy[2][1]
+旧图像[行][col+2]*Gy[2][0]
+旧图像[行+1][列]*Gy[1][2]
+旧图像[行+1][列+1]*Gy[1][1]
+旧图像[行+1][列+2]*Gy[1][0]
+旧图像[行+2][列]*Gy[0][2]
+旧图像[行+2][列+1]*Gy[0][1]
+旧图像[行+2][列+2]*Gy[0][0];
//不需要创建单独的变量来返回它
返回sqrt((convX*convX)+(convY*convY));
}
int main()
{
//={}将每个元素初始化为0,您不需要这样做:)只要您知道:)
//注意它在这里崩溃了,因为我的堆栈太小了,
/或者考虑使用动态数组(512×512相当大):
//双新图像[行][列]={};
//实际上并不需要该阵列,请参见下文
std::string filename=“oimage.txt”;
std::ofstreamnewimage{filename};
//无需创建另一个数组即可再次输出,
//只输出计算值-这不会忽略第一个/最后一个值
for(int rows=0;rows
newImage你所做的不仅仅是有点低效,而是——对不起——完全疯狂
对于图像的每个像素,您调用SobelConvolution,它依次调用ImageReader 18次(其中6次没有用,因为相应的系数为零)。但可怕的是,ImageReader每次都从文本文件执行完整的图像读取,在文本文件中,一个简单的数组查找就足够了
因此,您总共要执行4718592个文件流打开/关闭和1236950581248个文件值读取,其中只有1个打开/关闭和262144个读取就足够了(不包括单个读取比直接阵列访问成本高很多)一次完整的运行可能会持续两个小时或更长时间。您是否有意忽略NewImage
的第一个和最后一个值(只是将它们保留为0
)?是的。我认为这样做不会太复杂,而不必担心边缘上的值。这就是程序导致问题的原因吗?不是:)有太多不必要的循环。;)如果您没有启用优化功能进行编译,您应该-例如-O2
或-O3
用于clang和gcc co的选项mpilers.噢,我只是把它当作一个值来考虑,但我忘记了每次这样做时我实际上都在打开整个图像文件..谢谢!@RyanKim,你每次都在迭代整个数组:)我花了一点时间看你的评论。谢谢!这真的帮了我很大的忙。我不太确定我是否要声明数组n这样一来,我就添加了更多的变量,只是为了澄清,这使得它过于冗余。@RyanKim,不客气,如果你还有任何问题,请提问:)
double ImageReader(int r, int c)
{
double OrigImage[ROW][COL];
ifstream defaultImage ("image.txt");
if (defaultImage.good())
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
defaultImage >> OrigImage[i][j];
}
}
}
return OrigImage [r][c];
}
double SobelConvolution(int row, int col)
{
//ImageReader has been removed, it was unnecessary. The code has been moved here
double oldImage[ROW][COL];
std::ifstream defaultImage{ "image.txt" };
//Error handling if file doesn't exist - consider doing something else :)
if (!defaultImage.is_open())
return 0;
//Initialize array
for (int i = 0; i < ROW; ++i)
for (int j = 0; j < COL; ++j)
defaultImage >> oldImage[i][j];
//You should always declare variables where they are first used, this
//reduces the possibility of errors
//We can just access the array directly
double convX = oldImage[row][col] * Gx[2][2]
+ oldImage[row][col + 1] * Gx[2][1]
+ oldImage[row][col + 2] * Gx[2][0]
+ oldImage[row + 1][col] * Gx[1][2]
+ oldImage[row + 1][col + 1] * Gx[1][1]
+ oldImage[row + 1][col + 2] * Gx[1][0]
+ oldImage[row + 2][col] * Gx[0][2]
+ oldImage[row + 2][col + 1] * Gx[0][1]
+ oldImage[row + 2][col + 2] * Gx[0][0];
double convY = oldImage[row][col] * Gy[2][2]
+ oldImage[row][col + 1] * Gy[2][1]
+ oldImage[row][col + 2] * Gy[2][0]
+ oldImage[row + 1][col] * Gy[1][2]
+ oldImage[row + 1][col + 1] * Gy[1][1]
+ oldImage[row + 1][col + 2] * Gy[1][0]
+ oldImage[row + 2][col] * Gy[0][2]
+ oldImage[row + 2][col + 1] *Gy[0][1]
+ oldImage[row + 2][col + 2]*Gy[0][0];
//No need to create a separate variable just to return it
return sqrt((convX*convX) + (convY*convY));
}
int main()
{
//= {} Initializes every element to 0, you don't need to do it :) Just so you know :)
//Note that it crashes here, because my stack size was too small,
//maybe consider using a dynamic array (512 * 512 is pretty big) :)
//double NewImage[ROW][COL] = {};
//The array is not really needed, see below
std::string filename = "oimage.txt";
std::ofstream newImage{ filename };
//No need to create another array just to output it again,
//Just output the calculated values - this doesn't ignore the first/last values
for (int rows = 0; rows < ROW; rows++)
{
for (int cols = 0; cols < COL; cols++)
newImage << SobelConvolution(rows, cols) << " ";
newImage << '\n'; //std::endl flushes the stream, while \n does not - it is faster :)
}
newImage.close();
return 0;
}