鱼C论坛

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

C++转换函数

[复制链接]
发表于 昨天 18:32 | 显示全部楼层 |阅读模式

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

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

x
请直接将下面的几个函数修改成处理libtiff库打开1位深度的图像test.tif数据的处理代码不用Opencv函数,不要将图像处理转成8位深度做处理,直接对1位深度图像进行处理,处理完成后保存为2400dpi的1位深度文件,不使用类

// 精确识别纯黑色块区域(像素值为0)
Mat identifyPureBlackBlocks(const Mat& binary) {
    Mat black_blocks;

    // 直接识别值为0的纯黑色像素
    threshold(binary, black_blocks, 1, 255, THRESH_BINARY_INV);

    // 使用形态学闭操作连接相邻的黑色像素
    Mat kernel_connect = getStructuringElement(MORPH_RECT, Size(30, 30));
    morphologyEx(black_blocks, black_blocks, MORPH_CLOSE, kernel_connect);

    return black_blocks;
}

// 精确选择性膨胀函数
void preciseSelectiveDilate(const Mat& src, Mat& dst, int kernel_size) {
    // 步骤1:识别纯黑色块区域
    Mat black_blocks = identifyPureBlackBlocks(src);

    // 步骤2:在黑色块区域内识别白色像素(值为255)
    Mat white_pixels_in_black;
    threshold(src, white_pixels_in_black, 200, 255, THRESH_BINARY);

    // 步骤3:创建精确的膨胀目标掩膜
    Mat dilate_target = Mat::zeros(src.size(), CV_8UC1);

    // 精确遍历每个像素
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            // 如果当前像素在纯黑色块内且是白色像素,则标记为膨胀目标
            if (black_blocks.at<uchar>(i, j) == 255 && src.at<uchar>(i, j) == 255) {
                dilate_target.at<uchar>(i, j) = 255;
            }
        }
    }

    // 步骤4:对膨胀目标进行精确膨胀
    Mat kernel = getStructuringElement(MORPH_CROSS, Size(kernel_size, kernel_size));
    Mat dilated_target;
    dilate(dilate_target, dilated_target, kernel);

    // 步骤5:创建最终结果
    dst = src.clone();

    // 精确应用膨胀结果
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            // 只有在膨胀目标区域的像素才被修改为白色
            if (dilated_target.at<uchar>(i, j) == 255) {
                dst.at<uchar>(i, j) = 255;
            }
        }
    }
}
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 18:34 | 显示全部楼层
以下是使用libtiff库直接处理1位深度TIFF图像的代码:


  1. #include <tiffio.h>
  2. #include <vector>
  3. #include <algorithm>

  4. // 精确识别纯黑色块区域(像素值为0)
  5. std::vector<uint8_t> identifyPureBlackBlocks(const std::vector<uint8_t>& binary, int width, int height) {
  6.     std::vector<uint8_t> black_blocks(binary.size(), 0);
  7.    
  8.     // 直接识别值为0的纯黑色像素
  9.     for (int i = 0; i < height; i++) {
  10.         for (int j = 0; j < width; j++) {
  11.             int byte_pos = i * (width / 8) + j / 8;
  12.             int bit_pos = j % 8;
  13.             uint8_t pixel = (binary[byte_pos] >> (7 - bit_pos)) & 1;
  14.             
  15.             if (pixel == 0) {
  16.                 black_blocks[byte_pos] |= (1 << (7 - bit_pos));
  17.             }
  18.         }
  19.     }
  20.    
  21.     // 形态学闭操作连接相邻黑色像素
  22.     int kernel_size = 30;
  23.     std::vector<uint8_t> temp = black_blocks;
  24.    
  25.     // 膨胀
  26.     for (int i = 0; i < height; i++) {
  27.         for (int j = 0; j < width; j++) {
  28.             int byte_pos = i * (width / 8) + j / 8;
  29.             int bit_pos = j % 8;
  30.             
  31.             if ((black_blocks[byte_pos] >> (7 - bit_pos)) & 1) {
  32.                 for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
  33.                     for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
  34.                         int ni = i + ki;
  35.                         int nj = j + kj;
  36.                         if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
  37.                             int n_byte_pos = ni * (width / 8) + nj / 8;
  38.                             int n_bit_pos = nj % 8;
  39.                             temp[n_byte_pos] |= (1 << (7 - n_bit_pos));
  40.                         }
  41.                     }
  42.                 }
  43.             }
  44.         }
  45.     }
  46.    
  47.     // 腐蚀
  48.     black_blocks = temp;
  49.     temp = std::vector<uint8_t>(binary.size(), 0);
  50.    
  51.     for (int i = 0; i < height; i++) {
  52.         for (int j = 0; j < width; j++) {
  53.             int byte_pos = i * (width / 8) + j / 8;
  54.             int bit_pos = j % 8;
  55.             
  56.             bool all_black = true;
  57.             for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_black; ki++) {
  58.                 for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_black; kj++) {
  59.                     int ni = i + ki;
  60.                     int nj = j + kj;
  61.                     if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
  62.                         int n_byte_pos = ni * (width / 8) + nj / 8;
  63.                         int n_bit_pos = nj % 8;
  64.                         if (!((black_blocks[n_byte_pos] >> (7 - n_bit_pos)) & 1)) {
  65.                             all_black = false;
  66.                         }
  67.                     } else {
  68.                         all_black = false;
  69.                     }
  70.                 }
  71.             }
  72.             
  73.             if (all_black) {
  74.                 temp[byte_pos] |= (1 << (7 - bit_pos));
  75.             }
  76.         }
  77.     }
  78.    
  79.     return temp;
  80. }

  81. // 精确选择性膨胀函数
  82. void preciseSelectiveDilate(std::vector<uint8_t>& src, int width, int height, int kernel_size) {
  83.     // 识别纯黑色块区域
  84.     std::vector<uint8_t> black_blocks = identifyPureBlackBlocks(src, width, height);
  85.    
  86.     // 在黑色块区域内识别白色像素
  87.     std::vector<uint8_t> dilate_target(src.size(), 0);
  88.    
  89.     for (int i = 0; i < height; i++) {
  90.         for (int j = 0; j < width; j++) {
  91.             int byte_pos = i * (width / 8) + j / 8;
  92.             int bit_pos = j % 8;
  93.             
  94.             // 如果在纯黑色块内且是白色像素
  95.             if (((black_blocks[byte_pos] >> (7 - bit_pos)) & 1) &&
  96.                 ((src[byte_pos] >> (7 - bit_pos)) & 1)) {
  97.                 dilate_target[byte_pos] |= (1 << (7 - bit_pos));
  98.             }
  99.         }
  100.     }
  101.    
  102.     // 对目标像素进行膨胀
  103.     std::vector<uint8_t> result = src;
  104.    
  105.     for (int i = 0; i < height; i++) {
  106.         for (int j = 0; j < width; j++) {
  107.             int byte_pos = i * (width / 8) + j / 8;
  108.             int bit_pos = j % 8;
  109.             
  110.             if ((dilate_target[byte_pos] >> (7 - bit_pos)) & 1) {
  111.                 for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
  112.                     for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
  113.                         int ni = i + ki;
  114.                         int nj = j + kj;
  115.                         if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
  116.                             int n_byte_pos = ni * (width / 8) + nj / 8;
  117.                             int n_bit_pos = nj % 8;
  118.                             result[n_byte_pos] |= (1 << (7 - n_bit_pos));
  119.                         }
  120.                     }
  121.                 }
  122.             }
  123.         }
  124.     }
  125.    
  126.     src = result;
  127. }

  128. // 主处理函数
  129. int main() {
  130.     TIFF* tif_in = TIFFOpen("test.tif", "r");
  131.     if (!tif_in) return -1;
  132.    
  133.     uint32 width, height;
  134.     TIFFGetField(tif_in, TIFFTAG_IMAGEWIDTH, &width);
  135.     TIFFGetField(tif_in, TIFFTAG_IMAGELENGTH, &height);
  136.    
  137.     // 读取1位图像数据
  138.     std::vector<uint8_t> buffer(TIFFScanlineSize(tif_in) * height);
  139.     for (uint32 row = 0; row < height; row++) {
  140.         TIFFReadScanline(tif_in, &buffer[row * TIFFScanlineSize(tif_in)], row);
  141.     }
  142.     TIFFClose(tif_in);
  143.    
  144.     // 处理图像
  145.     preciseSelectiveDilate(buffer, width, height, 3);
  146.    
  147.     // 保存为2400dpi的1位图像
  148.     TIFF* tif_out = TIFFOpen("output.tif", "w");
  149.     TIFFSetField(tif_out, TIFFTAG_IMAGEWIDTH, width);
  150.     TIFFSetField(tif_out, TIFFTAG_IMAGELENGTH, height);
  151.     TIFFSetField(tif_out, TIFFTAG_BITSPERSAMPLE, 1);
  152.     TIFFSetField(tif_out, TIFFTAG_SAMPLESPERPIXEL, 1);
  153.     TIFFSetField(tif_out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  154.     TIFFSetField(tif_out, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
  155.     TIFFSetField(tif_out, TIFFTAG_XRESOLUTION, 2400.0);
  156.     TIFFSetField(tif_out, TIFFTAG_YRESOLUTION, 2400.0);
  157.     TIFFSetField(tif_out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  158.     TIFFSetField(tif_out, TIFFTAG_ROWSPERSTRIP, height);
  159.     TIFFSetField(tif_out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  160.    
  161.     for (uint32 row = 0; row < height; row++) {
  162.         TIFFWriteScanline(tif_out, &buffer[row * (width / 8)], row);
  163.     }
  164.    
  165.     TIFFClose(tif_out);
  166.     return 0;
  167. }
复制代码


主要修改说明:

1. 使用 std::vector<uint8_t> 存储1位图像数据
2. 直接操作位数据,保持1位深度不变
3. 手动实现形态学操作(膨胀、腐蚀)
4. 使用libtiff库读写TIFF文件
5. 设置输出分辨率为2400dpi
6. 使用CCITT FAX4压缩保持1位深度

编译时需要链接libtiff库:
-ltiff

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

使用道具 举报

 楼主| 发表于 昨天 18:37 | 显示全部楼层
FishC 发表于 2025-11-14 18:34
以下是使用libtiff库直接处理1位深度TIFF图像的代码:

忘了说了,我TIFF文件打开后是memset函数将数据存放于    unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * actual_height);里面,请修改一下
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 昨天 18:39 | 显示全部楼层
cxnet 发表于 2025-11-14 18:37
FishC 发表于 2025-11-14 18:34
以下是使用libtiff库 ...


以下是修改后的代码,直接处理1位深度TIFF数据:


  1. #include <tiffio.h>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <cstring>

  5. // 精确识别纯黑色块区域(像素值为0)
  6. void identifyPureBlackBlocks(unsigned char* src_data, unsigned char* black_blocks,
  7.                            int width, int height, int bytes_per_row) {
  8.     // 直接识别值为0的纯黑色像素
  9.     for (int i = 0; i < height; i++) {
  10.         for (int j = 0; j < width; j++) {
  11.             int byte_pos = i * bytes_per_row + j / 8;
  12.             int bit_pos = j % 8;
  13.             uint8_t pixel = (src_data[byte_pos] >> (7 - bit_pos)) & 1;
  14.             
  15.             if (pixel == 0) {
  16.                 black_blocks[byte_pos] |= (1 << (7 - bit_pos));
  17.             }
  18.         }
  19.     }
  20.    
  21.     // 形态学闭操作连接相邻黑色像素
  22.     int kernel_size = 30;
  23.     std::vector<uint8_t> temp_buffer(bytes_per_row * height, 0);
  24.    
  25.     // 膨胀操作
  26.     for (int i = 0; i < height; i++) {
  27.         for (int j = 0; j < width; j++) {
  28.             int byte_pos = i * bytes_per_row + j / 8;
  29.             int bit_pos = j % 8;
  30.             
  31.             if ((black_blocks[byte_pos] >> (7 - bit_pos)) & 1) {
  32.                 for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
  33.                     for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
  34.                         int ni = i + ki;
  35.                         int nj = j + kj;
  36.                         if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
  37.                             int n_byte_pos = ni * bytes_per_row + nj / 8;
  38.                             int n_bit_pos = nj % 8;
  39.                             temp_buffer[n_byte_pos] |= (1 << (7 - n_bit_pos));
  40.                         }
  41.                     }
  42.                 }
  43.             }
  44.         }
  45.     }
  46.    
  47.     // 腐蚀操作
  48.     memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
  49.     memset(temp_buffer.data(), 0, bytes_per_row * height);
  50.    
  51.     for (int i = 0; i < height; i++) {
  52.         for (int j = 0; j < width; j++) {
  53.             int byte_pos = i * bytes_per_row + j / 8;
  54.             int bit_pos = j % 8;
  55.             
  56.             bool all_set = true;
  57.             for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_set; ki++) {
  58.                 for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_set; kj++) {
  59.                     int ni = i + ki;
  60.                     int nj = j + kj;
  61.                     if (ni < 0 || ni >= height || nj < 0 || nj >= width) {
  62.                         all_set = false;
  63.                         continue;
  64.                     }
  65.                     int n_byte_pos = ni * bytes_per_row + nj / 8;
  66.                     int n_bit_pos = nj % 8;
  67.                     if (!((black_blocks[n_byte_pos] >> (7 - n_bit_pos)) & 1)) {
  68.                         all_set = false;
  69.                     }
  70.                 }
  71.             }
  72.             
  73.             if (all_set) {
  74.                 temp_buffer[byte_pos] |= (1 << (7 - bit_pos));
  75.             }
  76.         }
  77.     }
  78.    
  79.     memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
  80. }

  81. // 精确选择性膨胀函数
  82. void preciseSelectiveDilate(unsigned char* src_data, unsigned char* dst_data,
  83.                           int width, int height, int bytes_per_row, int kernel_size) {
  84.     // 步骤1:识别纯黑色块区域
  85.     unsigned char* black_blocks = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
  86.     memset(black_blocks, 0, bytes_per_row * height);
  87.     identifyPureBlackBlocks(src_data, black_blocks, width, height, bytes_per_row);
  88.    
  89.     // 步骤2:在黑色块区域内识别白色像素(值为1)
  90.     unsigned char* white_pixels_in_black = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
  91.     memset(white_pixels_in_black, 0, bytes_per_row * height);
  92.    
  93.     for (int i = 0; i < height; i++) {
  94.         for (int j = 0; j < width; j++) {
  95.             int byte_pos = i * bytes_per_row + j / 8;
  96.             int bit_pos = j % 8;
  97.             
  98.             // 如果当前像素在纯黑色块内且是白色像素,则标记
  99.             if (((black_blocks[byte_pos] >> (7 - bit_pos)) & 1) &&
  100.                 ((src_data[byte_pos] >> (7 - bit_pos)) & 1)) {
  101.                 white_pixels_in_black[byte_pos] |= (1 << (7 - bit_pos));
  102.             }
  103.         }
  104.     }
  105.    
  106.     // 步骤3:创建精确的膨胀目标掩膜
  107.     memcpy(dst_data, src_data, bytes_per_row * height);
  108.    
  109.     // 在白色像素位置进行膨胀
  110.     for (int i = 0; i < height; i++) {
  111.         for (int j = 0; j < width; j++) {
  112.             int byte_pos = i * bytes_per_row + j / 8;
  113.             int bit_pos = j % 8;
  114.             
  115.             if ((white_pixels_in_black[byte_pos] >> (7 - bit_pos)) & 1) {
  116.                 // 对当前白色像素进行膨胀
  117.                 for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
  118.                     for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
  119.                         int ni = i + ki;
  120.                         int nj = j + kj;
  121.                         if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
  122.                             int n_byte_pos = ni * bytes_per_row + nj / 8;
  123.                             int n_bit_pos = nj % 8;
  124.                             dst_data[n_byte_pos] |= (1 << (7 - n_bit_pos));
  125.                         }
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.     }
  131.    
  132.     _TIFFfree(black_blocks);
  133.     _TIFFfree(white_pixels_in_black);
  134. }

  135. // 保存为2400dpi的1位深度TIFF
  136. void saveAs2400DPI(const char* filename, unsigned char* data, int width, int height, int bytes_per_row) {
  137.     TIFF* tif = TIFFOpen(filename, "w");
  138.     if (!tif) return;
  139.    
  140.     TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
  141.     TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
  142.     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);
  143.     TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
  144.     TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
  145.     TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
  146.     TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  147.     TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
  148.    
  149.     // 设置2400dpi分辨率
  150.     TIFFSetField(tif, TIFFTAG_XRESOLUTION, 2400.0);
  151.     TIFFSetField(tif, TIFFTAG_YRESOLUTION, 2400.0);
  152.     TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
  153.    
  154.     for (int row = 0; row < height; row++) {
  155.         TIFFWriteScanline(tif, &data[row * bytes_per_row], row, 0);
  156.     }
  157.    
  158.     TIFFClose(tif);
  159. }
复制代码


使用示例:


  1. // 读取1位深度TIFF
  2. TIFF* tif = TIFFOpen("test.tif", "r");
  3. if (tif) {
  4.     uint32 width, height;
  5.     TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
  6.     TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
  7.    
  8.     int bytes_per_row = TIFFScanlineSize(tif);
  9.     unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
  10.    
  11.     for (int row = 0; row < height; row++) {
  12.         TIFFReadScanline(tif, &chunk_output_1bit[row * bytes_per_row], row);
  13.     }
  14.    
  15.     // 处理图像
  16.     unsigned char* result_data = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
  17.     preciseSelectiveDilate(chunk_output_1bit, result_data, width, height, bytes_per_row, 5);
  18.    
  19.     // 保存结果
  20.     saveAs2400DPI("output.tif", result_data, width, height, bytes_per_row);
  21.    
  22.     _TIFFfree(chunk_output_1bit);
  23.     _TIFFfree(result_data);
  24.     TIFFClose(tif);
  25. }
复制代码


主要修改点:

  • 使用 unsigned char* chunk_output_1bit 作为输入数据指针
  • 所有操作都直接在1位深度数据上进行,不转换为8位
  • 使用位操作来处理单个像素
  • 手动实现了形态学操作(膨胀、腐蚀)
  • 保存时设置2400dpi分辨率和1位深度
  • 使用CCITT FAX4压缩来保持1位深度


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

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-11-15 02:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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