Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我不知道';我不明白为什么我的c++;代码运行得太慢了_C++_Performance_Edge Detection_Sobel - Fatal编程技术网

C++ 我不知道';我不明白为什么我的c++;代码运行得太慢了

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

我正在研究用于边缘检测的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,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;rowsnewImage你所做的不仅仅是有点低效,而是——对不起——完全疯狂

对于图像的每个像素,您调用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;
}