写了一个lzw压缩程序,但是只能压缩txt文本,现在我用opencv把图像的每个像素的rgb读取到txt里进行lzw压缩,图像是7.18MB,但是读取后,存储图像像素的txt变成了36MB,压缩后根本不可能小于7MB,是因为RGB格式图像存储是其他方式吗?现在的问题就是如何正确读取图片像素到txt文本里,而不至于让txt太大了,不然我的压缩就没有意义了
压缩bmp格式就行了,这个数据没有压缩过,JPG那个已经压缩过了,那个读出来会很大,没意思
直接读图像文件,进行lzw压缩,再保存文件。
不要转txt,转txt肯定变大很多的。
如果你自己写的lzw不能支持二进制数据的处理,改进一下就行。
python
import cv2
import numpy as np
import struct
def compress_image(image_path, compressed_file_path):
# 读取图像数据
image = cv2.imread(image_path)
height, width, channel = image.shape
# 将图像数据转换为序列
seq = []
for y in range(height):
for x in range(width):
r, g, b = image[y, x]
seq.append((r << 16) | (g << 8) | b)
# 使用LZW压缩序列
dict_size = 256
dictionary = dict((i, chr(i)) for i in range(dict_size))
w = chr(seq[0] >> 16)
result = []
for i in range(1, len(seq)):
c = chr(seq[i] >> 16)
if w + c in dictionary:
w = w + c
else:
result.append(dictionary[w])
dictionary[w + c] = dict_size
dict_size += 1
w = c
if w:
result.append(dictionary[w])
# 将压缩后的数据写入二进制文件
with open(compressed_file_path, 'wb') as f:
f.write(struct.pack('I', dict_size))
for s in result:
f.write(struct.pack('H', dictionary[s]))
引用chatGPT作答,LZW 压缩是一种通用的压缩算法,可以用于压缩各种类型的数据,包括图像数据。在将图像数据压缩为文本格式后,您可以使用 LZW 压缩程序对其进行压缩。
您所遇到的问题可能是由于将 RGB 像素数据转换为文本格式时导致的文本大小增加。在将像素数据转换为文本时,建议使用二进制格式而不是文本格式,这可以显着减少文件大小。
在使用 OpenCV 读取像素数据时,您可以使用以下代码:
cv::Mat image = cv::imread("image.png", cv::IMREAD_COLOR);
cv::Mat pixels = image.reshape(1, image.rows * image.cols);
std::ofstream output("pixels.bin", std::ios::out | std::ios::binary);
output.write((char*)pixels.data, pixels.elemSize() * pixels.total());
output.close();
此代码将读取名为“image.png”的图像文件,将像素数据转换为单通道矩阵,并将其写入名为“pixels.bin”的二进制文件中。
接下来,您可以使用您的 LZW 压缩程序对生成的二进制文件进行压缩。
注意,压缩后的文件大小可能仍然比原始图像大小大,这取决于图像的内容和压缩算法的效率。但是,通过使用二进制格式,您应该能够减少文件大小并获得更好的压缩效果。
在将图像像素读取到文本文件中时,你需要注意一些细节。
首先,你需要明确图像是以何种方式存储像素的。如果你使用的是PNG、JPEG等格式的图像文件,那么它们的文件头部分通常包含图像的一些基本信息以及颜色模式。在读取图像像素时,你需要根据这些信息来确定每个像素的编码方式。例如,对于RGB彩色图像,每个像素通常包含3个字节的RGB值,但是对于索引色图像,每个像素通常只包含一个字节的颜色索引。
其次,你需要确定像素数据存储在文本文件中的编码方式,以确保文件大小不会过大。一种常用的方法是将像素的数值转换为一个固定长度的二进制字符串,并将其写入文本文件中。对于彩色图像,你需要分别对每个颜色通道进行这个操作,然后将它们按顺序依次写入文本文件中。
最后,当你读取像素时,你需要按照存储顺序正确地还原出像素的各个分量。如果像素数据被正确地编码和解码,那么你应该能够恢复出原始图像,且大小会小于或等于压缩后的文件大小。
除了手动实现LZW压缩,你也可以考虑使用现成的图像压缩库,例如GIF、PNG或JPEG等。这些库通常支持多种压缩算法,并且可以在保持图像质量的同时压缩图像大小。
图片肯定是压缩后的二进制数据,你那样做是对图片进行解压缩了,反而失去了意义。
给你一个建议,将图片进行base64编码,这样子都是文本了,在进行你的方式进行压缩,试试看
LZW(Lempel-Ziv-Welch)是一种常用的无损数据压缩算法,可以用于压缩图像、文本和其他类型的数据。在图像压缩中,LZW 压缩可以大幅减少图像文件的体积,提高图像传输的效率。下面是使用 LZW 压缩图像的步骤:
首先,需要读取要进行压缩的图像文件。可以使用 PHP 的 imagecreatefromjpeg()
、imagecreatefrompng()
、imagecreatefromgif()
等函数创建一个图像资源对象,然后使用 imagecolorat()
、imagesx()
、imagesy()
等函数获取图像的像素信息和尺寸信息。
$image = imagecreatefromjpeg("example.jpg"); // 读取 JPEG 图像
$width = imagesx($image); // 获取图像宽度
$height = imagesy($image); // 获取图像高度
// 像素遍历
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
$color = imagecolorat($image, $x, $y); // 获取像素颜色值
// TODO: 处理像素数据
}
}
imagedestroy($image); // 释放资源
在图像压缩中,需要将像素信息转换为二进制数据,然后使用 LZW 算法进行压缩。在 PHP 中,可以使用 pack()
函数将整数或字符串转换为二进制数据,使用 implode()
函数将多个二进制数据合并为一个字符串。然后,使用 LZW 算法对该字符串进行压缩。
$data = array(); // 用于存储像素颜色值
for ($y = 0; $y < $height; $y++) {
for ($x = 0; $x < $width; $x++) {
$color = imagecolorat($image, $x, $y);
$red = ($color >> 16) & 0xFF; // 获取红色分量
$green = ($color >> 8) & 0xFF; // 获取绿色分量
$blue = $color & 0xFF; // 获取蓝色分量
// 将 RGB 值转换为十进制整数
$value = $red * 65536 + $green * 256 + $blue;
$data[] = $value; // 存储像素颜色值
}
}
// 将像素颜色值转换为二进制数据
$bytes = array();
foreach ($data as $value) {
$bytes[] = pack("N", $value); // 将整数转换为网络字节序的二进制数据
}
$data_str = implode("", $bytes); // 合并多个二进制数据为一个字符串
// LZW 压缩
$compressed_str = gzcompress($data_str);
最后,需要将压缩后的数据写入文件。可以使用 PHP 的 file_put_contents()
函数将字符串写入文件。
file_put_contents("example.lzw", $compressed_str);
这样,就完成了使用 LZW 算法对图像进行压缩的操作。请注意,在解压缩时,需要先使用 gzuncompress()
函数解压缩数据,然后将字符串转换为整数或其他数据类型,并将像素颜色值写入新的图像文件中。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
RGB格式的图像每个像素通常占用3个字节,分别表示红、绿、蓝三个颜色通道的亮度值,因此读取到txt文本里面会占用较大的空间。一种更好的方式是将像素值转换成比特流,再写到文件里面,这样可以大大减小文件的大小。下面是一个读取RGB图像并将像素值转成比特流并写入文件的代码示例:
import cv2
import struct
# 从图像文件读取像素值并转成比特流
def convertToBits(imgFile):
img = cv2.imread(imgFile)
(h, w, c) = img.shape
bits = []
for i in range(h):
for j in range(w):
(b, g, r) = img[i,j]
bits.append(struct.pack('BBB', b, g, r))
return bits
# 将比特流写入文件
def writeToFile(bits, outFile):
with open(outFile, 'wb') as f:
for b in bits:
f.write(b)
# 使用示例
bits = convertToBits('image.jpg')
writeToFile(bits, 'image.bin')
在上面的代码中,cv2.imread
函数可以读取图像,并返回一个numpy
数组,数组的每个元素是一个包含三个数值的列表,分别是红、绿、蓝三个通道的亮度值。
struct.pack
函数可以将三个数值转换成一个二进制字符串,这个字符串的长度是3个字节,可以直接写入文件。最后调用open
函数打开一个二进制文件,并使用循环将每个二进制字符串写入文件。
注意:如果想要保留压缩图像的大小信息,可以在写入文件的时候先写入图像的宽、高和通道数,再写入压缩后的数据,这样可以在解压缩的时候还原图像大小。
如果我的回答解决了您的问题,请采纳!