library(readbitmap) library(pixmap) library(png) IMAGE_PATH <- "C:/users/drtr/Desktop/img.jpg" #путь к изображению #множитель размера сжатого изображения. 0.5 - изображение будет сжато в матрицу с числом ячеек в 2 раза меньше оригинала #сжатие происходит с потерей, и восстановленное изображение по качеству будет хуже оригинала SIZE_REDUCTION <- 0.05 bmpObj <- read.bitmap(IMAGE_PATH) # изображение представлено трёхмерной таблицей bmpObj # в которой первая координата - Y # вторая - X # третья - номер цветового канала (обычно три канала Red, Green, Blue) y_size <- dim(bmpObj)[1] x_size <- dim(bmpObj)[2] colors_size <- dim(bmpObj)[3] if(colors_size != 3){ # для простоты кода восстановления изображения - далее можно использовать только 3-х канальные (RGB) изображения. # Чёрно-белые, или с альфа-каналом будут неправильно обработаны при декомпрессии, для работы с ними нужно немного исправить код декомперессии stop("Unsupported image") } # трёхмерную таблицу конвертирую в двухмерную матрицу для работы с PCA bmpMatrix <- matrix(NA, nrow = y_size, ncol = x_size*colors_size) for(y in 1:y_size){ bmpMatrix[y,] <- c(bmpObj[y,,])*255 } #создание PCA. Значения пикселей уже отмасштабированы в [0:255]; повторное масштабирование не нужно. pcaObj <- prcomp(bmpMatrix, center = FALSE, scale. = FALSE) pcaCompN <- round(ncol(pcaObj$rotation)*SIZE_REDUCTION) # число PCA компонент. Масимальное число компонент = min(<высота изображения>, <ширина изображения> * 3) pcaRotation <- pcaObj$rotation[,1:pcaCompN, drop=FALSE] # создание новой матрицы, её размер будет меньше по сравнению с bmpMatrix пропорционально значению SIZE_REDUCTION bmpCompressed <- round(bmpMatrix %*% pcaRotation) # На данном этапе можно сохранить матрицы bmpCompressed и pcaRotation # И в будущем из них можно будет восстановить изображение (с потерей качества соответвенно SIZE_REDUCTION) # # Забавно, но размер pcaRotation + bmpCompressed может получится больше оригинального изображения. # Экономия места появится только если сжимать десятки изображений одной pca поворотной матрицей. # декомпрессия изображения # матрицу со сжатым изображением восстанавливаем к оригинальному размеру bmpDecompresed <- bmpCompressed %*% t(pcaRotation) bmpDecompresed[bmpDecompresed < 0] <- 0 bmpDecompresed[bmpDecompresed > 255] <- 255 # bmpDecompresed <- bmpCompressed # подготовка изображения для plot() pixmapObj <- pixmapRGB(data = bmpDecompresed, nrow=y_size, ncol=x_size) plot(pixmapObj) # write.pnm(object = pixmapObj, file=paste0(IMAGE_PATH,".PCA.",SIZE_REDUCTION, ".ppm")) #сохранение изображения в формате png pngTable <- matrix(bmpDecompresed/255) dim(pngTable) <- c(dim(bmpDecompresed)[1], dim(bmpDecompresed)[2]/3, 3) pngImg <- writePNG(image = pngTable, target = paste0(IMAGE_PATH,".PCA.",pcaCompN, ".png"))