鱼C论坛

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

C++分块加载1G以上超大TIF图片

[复制链接]
发表于 2024-10-5 11:46:55 | 显示全部楼层 |阅读模式

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

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

x
我最近用opencv对TIF图像做膨胀处理操作,小图片都是没问题,但是图像尺寸和分辨率比较大时就会报内存错误,请问怎样将图片进行分块加载后进行膨胀处理后再拼接成原图保存
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-10-5 11:51:18 | 显示全部楼层
要处理超大TIF图像,可以考虑通过分块加载的方式来解决内存不足的问题。以下是一个基本的步骤指导:

1. **安装和设置OpenCV**: 确保你的开发环境中已经安装了OpenCV,并进行了正确的配置。

2. **定义块的大小**: 根据你的内存和处理能力,选择合适的块大小。例如,256x256或512x512。

3. **读取图像尺寸**: 使用OpenCV读取图像信息,获取图像的宽和高。

4. **分块处理**:
   - 使用两个嵌套循环遍历每个块。在外层循环中遍历垂直方向的块,在内层循环中遍历水平方向的块。
   - 对于每个块,通过设置ROI(Region of Interest)读取子图。

5. **膨胀处理**: 对每个子图块进行膨胀操作。使用OpenCV提供的`cv::dilate`函数。

6. **拼接处理后的块**:
   - 创建一个与原图大小相同的空白图像。
   - 将处理过的每个块位置恢复到原图中的相应位置。

7. **保存结果**: 完成所有块的处理和拼接后,将完整图像保存到磁盘。

下面是一个简单的示例代码结构:

  1. #include <opencv2/opencv.hpp>
  2. #include <iostream>

  3. void processLargeImage(const std::string& imagePath, const std::string& resultPath, int blockSize) {
  4.     cv::Mat image = cv::imread(imagePath, cv::IMREAD_UNCHANGED);

  5.     if (image.empty()) {
  6.         std::cerr << "Image could not be loaded!" << std::endl;
  7.         return;
  8.     }

  9.     int width = image.cols;
  10.     int height = image.rows;
  11.     cv::Mat result = cv::Mat::zeros(height, width, image.type());

  12.     for (int y = 0; y < height; y += blockSize) {
  13.         for (int x = 0; x < width; x += blockSize) {
  14.             // Define the current block region
  15.             cv::Rect roi(x, y, std::min(blockSize, width - x), std::min(blockSize, height - y));
  16.             cv::Mat block = image(roi);

  17.             // Process the block (e.g., dilate)
  18.             cv::Mat processedBlock;
  19.             cv::dilate(block, processedBlock, cv::Mat());

  20.             // Copy processed block back to the result image
  21.             processedBlock.copyTo(result(roi));
  22.         }
  23.     }

  24.     // Save the result image
  25.     cv::imwrite(resultPath, result);
  26. }

  27. // Example usage
  28. int main() {
  29.     std::string imagePath = "large_image.tif";
  30.     std::string resultPath = "processed_image.tif";
  31.     int blockSize = 512;

  32.     processLargeImage(imagePath, resultPath, blockSize);
  33.     return 0;
  34. }
复制代码


确保在实际使用时根据具体需求调整块的大小和处理细节。以上代码展示了如何分块加载和处理超大图像。希望这能帮助到你!

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

使用道具 举报

 楼主| 发表于 2024-10-5 21:12:39 | 显示全部楼层
好的,按照你的方法已经可以正常处理了,另外怎样将拼接完成的图片显示到C++ MFC的图片控件里呢?最好可以支持放大缩小预览
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-5 21:12:58 | 显示全部楼层
cxnet 发表于 2024-10-05 21:12
好的,按照你的方法已经可以正常处理了,另外怎样将拼 ...


在C++ MFC中显示处理后的图像,并实现放大缩小预览,可以按以下步骤操作:

1. **准备图像控件**:
   - 在资源视图中,将一个`Picture Control`添加到你的对话框中。
   - 为`Picture Control`分配一个唯一的控制ID,例如`IDC_PICTURE`.

2. **添加MFC控件变量**:
   - 使用类向导为`Picture Control`添加一个控件变量,例如`m_PictureCtrl`。

3. **显示图像**:
   - 在MFC中,可以通过`CDC`和`CImage`类来显示OpenCV图像。首先,需要将OpenCV的`cv::Mat`数据转换成适合Windows API的格式,通常可以使用`CImage`类来实现。
   - 一个简单的方法是将OpenCV图像保存为暂时的位图文件,然后利用`CImage`或`HBITMAP`显示在Picture Control中。

4. **实现缩放功能**:
   - 使用鼠标滚轮或按钮添加缩放的功能,可以通过改变显示的图像尺寸来实现。

下面是一个示例代码,演示如何把OpenCV图像显示在MFC的Picture Control中:

  1. #include <opencv2/opencv.hpp>
  2. #include <afxwin.h>
  3. #include "resource.h"  // 你的资源文件

  4. class CMyDialog : public CDialogEx {
  5.     // ... 其他代码 ...

  6. public:
  7.     // Picture Control控件变量
  8.     CStatic m_PictureCtrl;

  9.     // 设置图像到控件
  10.     void SetImageToCtrl(const cv::Mat &image);

  11.     // 实现缩放
  12.     void ZoomImage(double scale);

  13.     // 步骤1: 对话框初始化
  14.     BOOL OnInitDialog() {
  15.         CDialogEx::OnInitDialog();
  16.         // 绑定控件变量和Picture Control
  17.         m_PictureCtrl.SubclassDlgItem(IDC_PICTURE, this);
  18.         return TRUE;  
  19.     }
  20. };

  21. void CMyDialog::SetImageToCtrl(const cv::Mat &image) {
  22.     if (image.empty())
  23.         return;

  24.     // 转换cv::Mat到CImage
  25.     CImage cimg;
  26.     BITMAPINFO bitInfo;
  27.     int imgWidth = image.cols;
  28.     int imgHeight = image.rows;
  29.    
  30.     bitInfo.bmiHeader.biBitCount = 24;  // 假设是8位颜色图
  31.     bitInfo.bmiHeader.biWidth = imgWidth;
  32.     bitInfo.bmiHeader.biHeight = -imgHeight;
  33.     bitInfo.bmiHeader.biPlanes = 1;
  34.     bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  35.     bitInfo.bmiHeader.biCompression = BI_RGB;
  36.     bitInfo.bmiHeader.biSizeImage = 0;
  37.     bitInfo.bmiHeader.biClrUsed = 0;
  38.     bitInfo.bmiHeader.biClrImportant = 0;

  39.     cimg.Create(imgWidth, imgHeight, 24);
  40.     GetDIBits(cimg.GetDC(), (HBITMAP)cimg, 0, imgHeight, image.data, &bitInfo, DIB_RGB_COLORS);

  41.     // 控件显示
  42.     CRect rect;
  43.     m_PictureCtrl.GetWindowRect(&rect);
  44.     m_PictureCtrl.SetBitmap((HBITMAP)cimg);
  45.     cimg.ReleaseDC();
  46. }

  47. void CMyDialog::ZoomImage(double scale) {
  48.     // 缩放图像具体实现
  49. }
复制代码


5. **缩放实现**:
   - 可以在`ZoomImage`函数中根据需要调整图像尺寸,改变比例系数来实现缩放功能。
   - 监听鼠标滚轮事件,可以使用`OnMouseWheel`函数来实现更精细的缩放控制。

通过这样的设置,你可以在MFC对话框中显示和操作大图像。随时调整控件尺寸和布局以适应更复杂的界面需求。如果你的应用需要更复杂的图形操作,比如拖拉缩放,可以考虑集成一个第三方的图像库。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-10 07:32

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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