如何使用R语言导入PGM文件并将其转换为方形TSV文件?
R语言实现PGM文件导入并转换为方形TSV文件
核心逻辑
PGM分ASCII(P2)和二进制(P5)两种格式,需先提取像素数据转为向量,再将向量转换为宽高相等的方形矩阵,最后导出为TSV文件。
方案一:处理ASCII格式PGM(P2)
适用于文本存储像素值的PGM文件,用基础R即可实现:
# 1. 读取并解析PGM文件 pgm_path <- "your_image.pgm" pgm_lines <- readLines(pgm_path) # 过滤注释行(以#开头的行) pgm_lines <- pgm_lines[!grepl("^#", pgm_lines)] # 提取图像宽高 dimensions <- as.integer(strsplit(pgm_lines[2], "\\s+")[[1]]) img_width <- dimensions[1] img_height <- dimensions[2] # 验证是否为方形图像 if (img_width != img_height) { stop("该PGM文件不是方形图像,无法转换为方形TSV") } # 提取像素值并转为数值向量 pixel_vector <- as.integer(unlist(strsplit(paste(pgm_lines[4:length(pgm_lines)], collapse = " "), "\\s+"))) # 2. 转换为方形矩阵 pgm_matrix <- matrix(pixel_vector, nrow = img_height, ncol = img_width, byrow = TRUE) # 3. 导出为TSV文件 write.table(pgm_matrix, file = "square_output.tsv", sep = "\t", row.names = FALSE, col.names = FALSE)
方案二:处理二进制格式PGM(P5)
针对二进制存储的PGM文件,需用readBin读取像素数据:
# 1. 读取二进制PGM文件 pgm_path <- "binary_image.pgm" pgm_con <- file(pgm_path, "rb") # 读取头信息并过滤注释 pgm_header <- readLines(pgm_con, n = 3) pgm_header <- pgm_header[!grepl("^#", pgm_header)] # 提取宽高和最大灰度值 dimensions <- as.integer(strsplit(pgm_header[2], "\\s+")[[1]]) img_width <- dimensions[1] img_height <- dimensions[2] max_gray <- as.integer(pgm_header[3]) # 验证方形图像 if (img_width != img_height) { close(pgm_con) stop("该PGM文件不是方形图像,无法转换为方形TSV") } # 读取二进制像素数据(根据最大灰度值判断字节大小) pixel_vector <- readBin( pgm_con, integer(), n = img_width * img_height, size = ifelse(max_gray > 255, 2, 1), endian = "big" ) close(pgm_con) # 2. 转换为方形矩阵并导出TSV pgm_matrix <- matrix(pixel_vector, nrow = img_height, ncol = img_width, byrow = TRUE) write.table(pgm_matrix, file = "binary_square_output.tsv", sep = "\t", row.names = FALSE, col.names = FALSE)
封装为复用函数
将上述逻辑整合为函数,支持自动识别PGM格式:
pgm_to_square_tsv <- function(input_pgm, output_tsv) { # 尝试读取ASCII格式 tryCatch({ pgm_lines <- readLines(input_pgm) pgm_lines <- pgm_lines[!grepl("^#", pgm_lines)] if (pgm_lines[1] != "P2") { stop("不是ASCII格式PGM,尝试二进制读取") } dimensions <- as.integer(strsplit(pgm_lines[2], "\\s+")[[1]]) img_width <- dimensions[1] img_height <- dimensions[2] if (img_width != img_height) stop("非方形图像") pixel_vector <- as.integer(unlist(strsplit(paste(pgm_lines[4:length(pgm_lines)], collapse = " "), "\\s+"))) }, error = function(e) { # 切换为二进制读取 pgm_con <- file(input_pgm, "rb") on.exit(close(pgm_con)) pgm_header <- readLines(pgm_con, n = 3) pgm_header <- pgm_header[!grepl("^#", pgm_header)] if (pgm_header[1] != "P5") stop("不支持的PGM格式(仅支持P2/P5)") dimensions <- as.integer(strsplit(pgm_header[2], "\\s+")[[1]]) img_width <<- dimensions[1] img_height <<- dimensions[2] if (img_width != img_height) stop("非方形图像") max_gray <- as.integer(pgm_header[3]) pixel_vector <<- readBin( pgm_con, integer(), n = img_width * img_height, size = ifelse(max_gray > 255, 2, 1), endian = "big" ) }) # 转换矩阵并导出 pgm_matrix <- matrix(pixel_vector, nrow = img_height, ncol = img_width, byrow = TRUE) write.table(pgm_matrix, file = output_tsv, sep = "\t", row.names = FALSE, col.names = FALSE) cat("转换完成,文件已保存至:", output_tsv, "\n") } # 使用示例 pgm_to_square_tsv("test_image.pgm", "result.tsv")
内容的提问来源于stack exchange,提问作者Aoife
相关产品推荐
相关产品推荐

