cxnet 发表于 5 天前

C++转换函数

请直接将下面的几个函数修改成处理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;
            }
      }
    }
}

FishC 发表于 5 天前

以下是使用libtiff库直接处理1位深度TIFF图像的代码:


#include <tiffio.h>
#include <vector>
#include <algorithm>

// 精确识别纯黑色块区域(像素值为0)
std::vector<uint8_t> identifyPureBlackBlocks(const std::vector<uint8_t>& binary, int width, int height) {
    std::vector<uint8_t> black_blocks(binary.size(), 0);
   
    // 直接识别值为0的纯黑色像素
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * (width / 8) + j / 8;
            int bit_pos = j % 8;
            uint8_t pixel = (binary >> (7 - bit_pos)) & 1;
            
            if (pixel == 0) {
                black_blocks |= (1 << (7 - bit_pos));
            }
      }
    }
   
    // 形态学闭操作连接相邻黑色像素
    int kernel_size = 30;
    std::vector<uint8_t> temp = black_blocks;
   
    // 膨胀
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * (width / 8) + j / 8;
            int bit_pos = j % 8;
            
            if ((black_blocks >> (7 - bit_pos)) & 1) {
                for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
                  for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
                        int ni = i + ki;
                        int nj = j + kj;
                        if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                            int n_byte_pos = ni * (width / 8) + nj / 8;
                            int n_bit_pos = nj % 8;
                            temp |= (1 << (7 - n_bit_pos));
                        }
                  }
                }
            }
      }
    }
   
    // 腐蚀
    black_blocks = temp;
    temp = std::vector<uint8_t>(binary.size(), 0);
   
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * (width / 8) + j / 8;
            int bit_pos = j % 8;
            
            bool all_black = true;
            for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_black; ki++) {
                for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_black; kj++) {
                  int ni = i + ki;
                  int nj = j + kj;
                  if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                        int n_byte_pos = ni * (width / 8) + nj / 8;
                        int n_bit_pos = nj % 8;
                        if (!((black_blocks >> (7 - n_bit_pos)) & 1)) {
                            all_black = false;
                        }
                  } else {
                        all_black = false;
                  }
                }
            }
            
            if (all_black) {
                temp |= (1 << (7 - bit_pos));
            }
      }
    }
   
    return temp;
}

// 精确选择性膨胀函数
void preciseSelectiveDilate(std::vector<uint8_t>& src, int width, int height, int kernel_size) {
    // 识别纯黑色块区域
    std::vector<uint8_t> black_blocks = identifyPureBlackBlocks(src, width, height);
   
    // 在黑色块区域内识别白色像素
    std::vector<uint8_t> dilate_target(src.size(), 0);
   
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * (width / 8) + j / 8;
            int bit_pos = j % 8;
            
            // 如果在纯黑色块内且是白色像素
            if (((black_blocks >> (7 - bit_pos)) & 1) &&
                ((src >> (7 - bit_pos)) & 1)) {
                dilate_target |= (1 << (7 - bit_pos));
            }
      }
    }
   
    // 对目标像素进行膨胀
    std::vector<uint8_t> result = src;
   
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * (width / 8) + j / 8;
            int bit_pos = j % 8;
            
            if ((dilate_target >> (7 - bit_pos)) & 1) {
                for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
                  for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
                        int ni = i + ki;
                        int nj = j + kj;
                        if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                            int n_byte_pos = ni * (width / 8) + nj / 8;
                            int n_bit_pos = nj % 8;
                            result |= (1 << (7 - n_bit_pos));
                        }
                  }
                }
            }
      }
    }
   
    src = result;
}

// 主处理函数
int main() {
    TIFF* tif_in = TIFFOpen("test.tif", "r");
    if (!tif_in) return -1;
   
    uint32 width, height;
    TIFFGetField(tif_in, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif_in, TIFFTAG_IMAGELENGTH, &height);
   
    // 读取1位图像数据
    std::vector<uint8_t> buffer(TIFFScanlineSize(tif_in) * height);
    for (uint32 row = 0; row < height; row++) {
      TIFFReadScanline(tif_in, &buffer, row);
    }
    TIFFClose(tif_in);
   
    // 处理图像
    preciseSelectiveDilate(buffer, width, height, 3);
   
    // 保存为2400dpi的1位图像
    TIFF* tif_out = TIFFOpen("output.tif", "w");
    TIFFSetField(tif_out, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tif_out, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tif_out, TIFFTAG_BITSPERSAMPLE, 1);
    TIFFSetField(tif_out, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tif_out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tif_out, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
    TIFFSetField(tif_out, TIFFTAG_XRESOLUTION, 2400.0);
    TIFFSetField(tif_out, TIFFTAG_YRESOLUTION, 2400.0);
    TIFFSetField(tif_out, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    TIFFSetField(tif_out, TIFFTAG_ROWSPERSTRIP, height);
    TIFFSetField(tif_out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
   
    for (uint32 row = 0; row < height; row++) {
      TIFFWriteScanline(tif_out, &buffer, row);
    }
   
    TIFFClose(tif_out);
    return 0;
}


主要修改说明:

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

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

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

cxnet 发表于 5 天前

FishC 发表于 2025-11-14 18:34
以下是使用libtiff库直接处理1位深度TIFF图像的代码:




忘了说了,我TIFF文件打开后是memset函数将数据存放于    unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * actual_height);里面,请修改一下

FishC 发表于 5 天前

cxnet 发表于 2025-11-14 18:37
FishC 发表于 2025-11-14 18:34
以下是使用libtiff库 ...

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


#include <tiffio.h>
#include <vector>
#include <algorithm>
#include <cstring>

// 精确识别纯黑色块区域(像素值为0)
void identifyPureBlackBlocks(unsigned char* src_data, unsigned char* black_blocks,
                           int width, int height, int bytes_per_row) {
    // 直接识别值为0的纯黑色像素
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * bytes_per_row + j / 8;
            int bit_pos = j % 8;
            uint8_t pixel = (src_data >> (7 - bit_pos)) & 1;
            
            if (pixel == 0) {
                black_blocks |= (1 << (7 - bit_pos));
            }
      }
    }
   
    // 形态学闭操作连接相邻黑色像素
    int kernel_size = 30;
    std::vector<uint8_t> temp_buffer(bytes_per_row * height, 0);
   
    // 膨胀操作
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * bytes_per_row + j / 8;
            int bit_pos = j % 8;
            
            if ((black_blocks >> (7 - bit_pos)) & 1) {
                for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
                  for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
                        int ni = i + ki;
                        int nj = j + kj;
                        if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                            int n_byte_pos = ni * bytes_per_row + nj / 8;
                            int n_bit_pos = nj % 8;
                            temp_buffer |= (1 << (7 - n_bit_pos));
                        }
                  }
                }
            }
      }
    }
   
    // 腐蚀操作
    memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
    memset(temp_buffer.data(), 0, bytes_per_row * height);
   
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * bytes_per_row + j / 8;
            int bit_pos = j % 8;
            
            bool all_set = true;
            for (int ki = -kernel_size/2; ki <= kernel_size/2 && all_set; ki++) {
                for (int kj = -kernel_size/2; kj <= kernel_size/2 && all_set; kj++) {
                  int ni = i + ki;
                  int nj = j + kj;
                  if (ni < 0 || ni >= height || nj < 0 || nj >= width) {
                        all_set = false;
                        continue;
                  }
                  int n_byte_pos = ni * bytes_per_row + nj / 8;
                  int n_bit_pos = nj % 8;
                  if (!((black_blocks >> (7 - n_bit_pos)) & 1)) {
                        all_set = false;
                  }
                }
            }
            
            if (all_set) {
                temp_buffer |= (1 << (7 - bit_pos));
            }
      }
    }
   
    memcpy(black_blocks, temp_buffer.data(), bytes_per_row * height);
}

// 精确选择性膨胀函数
void preciseSelectiveDilate(unsigned char* src_data, unsigned char* dst_data,
                        int width, int height, int bytes_per_row, int kernel_size) {
    // 步骤1:识别纯黑色块区域
    unsigned char* black_blocks = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
    memset(black_blocks, 0, bytes_per_row * height);
    identifyPureBlackBlocks(src_data, black_blocks, width, height, bytes_per_row);
   
    // 步骤2:在黑色块区域内识别白色像素(值为1)
    unsigned char* white_pixels_in_black = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
    memset(white_pixels_in_black, 0, bytes_per_row * height);
   
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * bytes_per_row + j / 8;
            int bit_pos = j % 8;
            
            // 如果当前像素在纯黑色块内且是白色像素,则标记
            if (((black_blocks >> (7 - bit_pos)) & 1) &&
                ((src_data >> (7 - bit_pos)) & 1)) {
                white_pixels_in_black |= (1 << (7 - bit_pos));
            }
      }
    }
   
    // 步骤3:创建精确的膨胀目标掩膜
    memcpy(dst_data, src_data, bytes_per_row * height);
   
    // 在白色像素位置进行膨胀
    for (int i = 0; i < height; i++) {
      for (int j = 0; j < width; j++) {
            int byte_pos = i * bytes_per_row + j / 8;
            int bit_pos = j % 8;
            
            if ((white_pixels_in_black >> (7 - bit_pos)) & 1) {
                // 对当前白色像素进行膨胀
                for (int ki = -kernel_size/2; ki <= kernel_size/2; ki++) {
                  for (int kj = -kernel_size/2; kj <= kernel_size/2; kj++) {
                        int ni = i + ki;
                        int nj = j + kj;
                        if (ni >= 0 && ni < height && nj >= 0 && nj < width) {
                            int n_byte_pos = ni * bytes_per_row + nj / 8;
                            int n_bit_pos = nj % 8;
                            dst_data |= (1 << (7 - n_bit_pos));
                        }
                  }
                }
            }
      }
    }
   
    _TIFFfree(black_blocks);
    _TIFFfree(white_pixels_in_black);
}

// 保存为2400dpi的1位深度TIFF
void saveAs2400DPI(const char* filename, unsigned char* data, int width, int height, int bytes_per_row) {
    TIFF* tif = TIFFOpen(filename, "w");
    if (!tif) return;
   
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
    TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
   
    // 设置2400dpi分辨率
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, 2400.0);
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, 2400.0);
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
   
    for (int row = 0; row < height; row++) {
      TIFFWriteScanline(tif, &data, row, 0);
    }
   
    TIFFClose(tif);
}


使用示例:


// 读取1位深度TIFF
TIFF* tif = TIFFOpen("test.tif", "r");
if (tif) {
    uint32 width, height;
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
   
    int bytes_per_row = TIFFScanlineSize(tif);
    unsigned char* chunk_output_1bit = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
   
    for (int row = 0; row < height; row++) {
      TIFFReadScanline(tif, &chunk_output_1bit, row);
    }
   
    // 处理图像
    unsigned char* result_data = (unsigned char*)_TIFFmalloc(bytes_per_row * height);
    preciseSelectiveDilate(chunk_output_1bit, result_data, width, height, bytes_per_row, 5);
   
    // 保存结果
    saveAs2400DPI("output.tif", result_data, width, height, bytes_per_row);
   
    _TIFFfree(chunk_output_1bit);
    _TIFFfree(result_data);
    TIFFClose(tif);
}


主要修改点:


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


以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: C++转换函数