鱼C论坛

 找回密码
 立即注册
查看: 610|回复: 3

[已解决]C++ MFC 2G大图分块载入处理

[复制链接]
发表于 2024-10-5 22:06:25 From FishC Mobile | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我在C++ MFC里用opencv对TIF图像做膨胀处理操作,小图片都是没问题,但是图像尺寸和分辨率比较大时就会报内存错误,请问怎样将图片进行分块加载后进行膨胀处理后并转换为1bit的二值图,再拼接成原图,再将拼接完成的图片从MFC的图片控件上显示出来,最好可以放大缩小预览图片,最后将拼接完的图片保存到文件。
最佳答案
2024-10-5 22:17:45
cxnet 发表于 2024-10-05 22:17
能帮我把上面的流程用C++  MFC写个代码吗?谢谢


由于完整实现的代码可能较长且具体细节会根据实际需求有所不同,我将为你提供一个简化版的代码示例,帮助你理解如何实现超大图像的分块处理、膨胀、二值化和拼接显示。

以下是实现上述流程的示例代码:

  1. #include <afxwin.h>
  2. #include <opencv2/opencv.hpp>

  3. using namespace cv;

  4. class CMyFrame : public CFrameWnd
  5. {
  6. public:
  7.     CMyFrame()
  8.     {
  9.         Create(NULL, _T("MFC and OpenCV Large Image Processing"));
  10.     }

  11. protected:
  12.     afx_msg void OnPaint()
  13.     {
  14.         CPaintDC dc(this);
  15.         Mat largeImage = imread("large_image.tif", IMREAD_GRAYSCALE);

  16.         // 检查图像是否载入
  17.         if (largeImage.empty())
  18.         {
  19.             MessageBox(_T("Could not load image"), _T("Error"), MB_OK);
  20.             return;
  21.         }

  22.         int blockSize = 512;
  23.         Mat resultImage(largeImage.size(), CV_8UC1);

  24.         for (int y = 0; y < largeImage.rows; y += blockSize)
  25.         {
  26.             for (int x = 0; x < largeImage.cols; x += blockSize)
  27.             {
  28.                 // 定义感兴趣区域
  29.                 Rect roi(x, y, std::min(blockSize, largeImage.cols - x), std::min(blockSize, largeImage.rows - y));
  30.                 Mat block = largeImage(roi);

  31.                 // 膨胀
  32.                 Mat dilatedBlock;
  33.                 dilate(block, dilatedBlock, Mat());

  34.                 // 二值化
  35.                 Mat binaryBlock;
  36.                 threshold(dilatedBlock, binaryBlock, 128, 255, THRESH_BINARY);

  37.                 // 将结果拷贝回结果图像
  38.                 binaryBlock.copyTo(resultImage(roi));
  39.             }
  40.         }

  41.         // 显示图像
  42.         CImage img;
  43.         img.Create(resultImage.cols, resultImage.rows, 8);
  44.         for (int y = 0; y < resultImage.rows; ++y)
  45.         {
  46.             for (int x = 0; x < resultImage.cols; ++x)
  47.             {
  48.                 BYTE pixelValue = (resultImage.at<uchar>(y, x) / 255) * 255;
  49.                 img.SetPixel(x, y, RGB(pixelValue, pixelValue, pixelValue));
  50.             }
  51.         }
  52.         img.Draw(dc.m_hDC, 0, 0);

  53.         // 选择性保存拼接图像
  54.         imwrite("processed_image.tif", resultImage);
  55.     }

  56.     DECLARE_MESSAGE_MAP()
  57. };

  58. BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
  59.     ON_WM_PAINT()
  60. END_MESSAGE_MAP()

  61. class CMyApp : public CWinApp
  62. {
  63. public:
  64.     BOOL InitInstance()
  65.     {
  66.         CMyFrame *Frame = new CMyFrame();
  67.         m_pMainWnd = Frame;
  68.         Frame->ShowWindow(SW_SHOW);
  69.         Frame->UpdateWindow();
  70.         return TRUE;
  71.     }
  72. };

  73. CMyApp theApp;
复制代码


### 代码说明:
1. **分块处理**:采用512x512的块进行遍历处理,每次从图像中截取一个块。
2. **膨胀和二值化**:对每个块应用膨胀处理和二值化。
3. **结果拼接**:将处理后的块复制回结果图像的相应位置。
4. **显示**:使用MFC的`CImage`类来显示处理后的图像。
5. **保存**:处理完成后,将结果图像另存为`tif`文件。

注意:这个代码是描述性的,在实际使用中,你可能需要根据平台设置、OpenCV环境配置或具体需求作调整。另需考虑缩放功能和内存优化等额外功能。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-5 22:06:36 | 显示全部楼层
处理超大图像时,可以将图像分块处理以减少内存占用。以下是一个简要的步骤指南:

1. **分块加载和处理图像:**
   - 读入超大图像文件的基本信息(如宽高、通道数)。
   - 根据内存限制确定适当的块大小(例如,512x512像素)。
   - 使用循环将图像分块读取,每个块作为一个独立的小图像进行操作。
   - 使用OpenCV对每个块进行膨胀处理。

2. **转换为1bit二值图:**
   - 对每个膨胀处理后的块进行二值化处理,例如使用`cv::threshold()`函数来实现。

3. **拼接图像:**
   - 创建一个空的大图像来存放拼接后的结果。
   - 将处理后的各个块放置在对应的位置上,注意在拷贝过程中考虑边界条件。

4. **在MFC中显示:**
   - 使用MFC的GDI+或其他控件将图像显示在窗口上。
   - 为实现缩放功能,可以使用控件的缩放特性或者用GDI+手动实现。

5. **保存拼接图像:**
   - 使用OpenCV的`cv::imwrite()`函数将最终拼接的图像保存到文件中。

这是一个基本步骤,具体实现时需要考虑内存管理、边缘处理等细节。根据你的实际需求,可以对代码进行优化以更高效地处理数据。希望这一思路能帮助你完成任务。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-5 22:17:35 From FishC Mobile | 显示全部楼层
FishC 发表于 2024-10-5 22:06
处理超大图像时,可以将图像分块处理以减少内存占用。以下是一个简要的步骤指南:

1. **分块加载和处理 ...

能帮我把上面的流程用C++  MFC写个代码吗?谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-5 22:17:45 | 显示全部楼层    本楼为最佳答案   
cxnet 发表于 2024-10-05 22:17
能帮我把上面的流程用C++  MFC写个代码吗?谢谢


由于完整实现的代码可能较长且具体细节会根据实际需求有所不同,我将为你提供一个简化版的代码示例,帮助你理解如何实现超大图像的分块处理、膨胀、二值化和拼接显示。

以下是实现上述流程的示例代码:

  1. #include <afxwin.h>
  2. #include <opencv2/opencv.hpp>

  3. using namespace cv;

  4. class CMyFrame : public CFrameWnd
  5. {
  6. public:
  7.     CMyFrame()
  8.     {
  9.         Create(NULL, _T("MFC and OpenCV Large Image Processing"));
  10.     }

  11. protected:
  12.     afx_msg void OnPaint()
  13.     {
  14.         CPaintDC dc(this);
  15.         Mat largeImage = imread("large_image.tif", IMREAD_GRAYSCALE);

  16.         // 检查图像是否载入
  17.         if (largeImage.empty())
  18.         {
  19.             MessageBox(_T("Could not load image"), _T("Error"), MB_OK);
  20.             return;
  21.         }

  22.         int blockSize = 512;
  23.         Mat resultImage(largeImage.size(), CV_8UC1);

  24.         for (int y = 0; y < largeImage.rows; y += blockSize)
  25.         {
  26.             for (int x = 0; x < largeImage.cols; x += blockSize)
  27.             {
  28.                 // 定义感兴趣区域
  29.                 Rect roi(x, y, std::min(blockSize, largeImage.cols - x), std::min(blockSize, largeImage.rows - y));
  30.                 Mat block = largeImage(roi);

  31.                 // 膨胀
  32.                 Mat dilatedBlock;
  33.                 dilate(block, dilatedBlock, Mat());

  34.                 // 二值化
  35.                 Mat binaryBlock;
  36.                 threshold(dilatedBlock, binaryBlock, 128, 255, THRESH_BINARY);

  37.                 // 将结果拷贝回结果图像
  38.                 binaryBlock.copyTo(resultImage(roi));
  39.             }
  40.         }

  41.         // 显示图像
  42.         CImage img;
  43.         img.Create(resultImage.cols, resultImage.rows, 8);
  44.         for (int y = 0; y < resultImage.rows; ++y)
  45.         {
  46.             for (int x = 0; x < resultImage.cols; ++x)
  47.             {
  48.                 BYTE pixelValue = (resultImage.at<uchar>(y, x) / 255) * 255;
  49.                 img.SetPixel(x, y, RGB(pixelValue, pixelValue, pixelValue));
  50.             }
  51.         }
  52.         img.Draw(dc.m_hDC, 0, 0);

  53.         // 选择性保存拼接图像
  54.         imwrite("processed_image.tif", resultImage);
  55.     }

  56.     DECLARE_MESSAGE_MAP()
  57. };

  58. BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
  59.     ON_WM_PAINT()
  60. END_MESSAGE_MAP()

  61. class CMyApp : public CWinApp
  62. {
  63. public:
  64.     BOOL InitInstance()
  65.     {
  66.         CMyFrame *Frame = new CMyFrame();
  67.         m_pMainWnd = Frame;
  68.         Frame->ShowWindow(SW_SHOW);
  69.         Frame->UpdateWindow();
  70.         return TRUE;
  71.     }
  72. };

  73. CMyApp theApp;
复制代码


### 代码说明:
1. **分块处理**:采用512x512的块进行遍历处理,每次从图像中截取一个块。
2. **膨胀和二值化**:对每个块应用膨胀处理和二值化。
3. **结果拼接**:将处理后的块复制回结果图像的相应位置。
4. **显示**:使用MFC的`CImage`类来显示处理后的图像。
5. **保存**:处理完成后,将结果图像另存为`tif`文件。

注意:这个代码是描述性的,在实际使用中,你可能需要根据平台设置、OpenCV环境配置或具体需求作调整。另需考虑缩放功能和内存优化等额外功能。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-10 08:29

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表