鱼C论坛

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

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

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

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

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

x
我最近用opencv对TIF图像做膨胀处理操作,小图片都是没问题,但是图像尺寸和分辨率比较大时就会报内存错误,请问怎样将图片进行分块加载后进行膨胀处理后再拼接成原图保存
想知道小甲鱼最近在做啥?请访问 -> 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. **保存结果**: 完成所有块的处理和拼接后,将完整图像保存到磁盘。

下面是一个简单的示例代码结构:
#include <opencv2/opencv.hpp>
#include <iostream>

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

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

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

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

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

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

    // Save the result image
    cv::imwrite(resultPath, result);
}

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

    processLargeImage(imagePath, resultPath, blockSize);
    return 0;
}

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-5 21:12:39 | 显示全部楼层
好的,按照你的方法已经可以正常处理了,另外怎样将拼接完成的图片显示到C++ MFC的图片控件里呢?最好可以支持放大缩小预览
想知道小甲鱼最近在做啥?请访问 -> 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中:
#include <opencv2/opencv.hpp>
#include <afxwin.h>
#include "resource.h"  // 你的资源文件 

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

public:
    // Picture Control控件变量
    CStatic m_PictureCtrl;

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

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

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

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

    // 转换cv::Mat到CImage
    CImage cimg;
    BITMAPINFO bitInfo;
    int imgWidth = image.cols;
    int imgHeight = image.rows;
    
    bitInfo.bmiHeader.biBitCount = 24;  // 假设是8位颜色图
    bitInfo.bmiHeader.biWidth = imgWidth;
    bitInfo.bmiHeader.biHeight = -imgHeight;
    bitInfo.bmiHeader.biPlanes = 1;
    bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitInfo.bmiHeader.biCompression = BI_RGB;
    bitInfo.bmiHeader.biSizeImage = 0;
    bitInfo.bmiHeader.biClrUsed = 0;
    bitInfo.bmiHeader.biClrImportant = 0;

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

    // 控件显示
    CRect rect;
    m_PictureCtrl.GetWindowRect(&rect);
    m_PictureCtrl.SetBitmap((HBITMAP)cimg);
    cimg.ReleaseDC();
}

void CMyDialog::ZoomImage(double scale) {
    // 缩放图像具体实现
}

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 01:53

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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