16位图像转换为8位图像(c++,python)

如之前所说,我们需要将16位图像转换为8位图像;16位图像的像素值一共有:

2^16=65536种颜色;

而8位位图像只有:

2^8=256种颜色,传统的位数转换都是:像素值*256/65536,比如photoshop,以及matlab的im2uint8函数都是如此,在一般场景下是没有问题的,我们姑且称之为“真转换”,而如果是labelme得到的label.png标注图像在进行转换时,由于每个类别的像素值从0开始赋值,如0,1,2,3,4.......如果进行“真转换”的话,由于这些值都太小,基本转换后的像素值都是(0,1)之间,所以都变成了0,所以我们需要将16位转换位8位的时候还保留住原来的像素值,这种只改变位数,而不改变具体数值的转换方法,姑且称之为“伪转换”;

而解决的思路也很简单,图像说白了也就是一个矩阵,像素值也就是一个数值而已,我们只需要把表示类别的像素值找出来,并且把他们的值投射到8位即可:

使用的软件环境如下:

  • Python 3.6.3
  • VS2013
  • OPENCV 2.4.11
  • PIL
  • Labelme 2.8.0

首先,C++使用opencv转化,核心代码如下:(完整代码(批量转换,速度最快,需要配置opencv):点击打开链接

for (int k = 0; k<src.rows; k++)
		{
			for (int kk = 0; kk<src.cols; kk++)
			{
				int n = src.at<ushort>(k, kk);
				ff.at<uchar>(k, kk) = n;
			}
		}

python使用PIL进行转换,更加简单,核心语句就一行(完整代码(推荐,批量转化,速度也很快,但是少了配置opencv的麻烦):点击下载完整python转换代码):

img = Image.fromarray(np.uint8(img))

转换完成后,可以使用软件查看时候变为8位,但是打开图片依然是一片黑:


如果需要提高类别之间的差异性,可以直接乘以一个较大的值:如下:

img = Image.fromarray(np.uint8(img)*20)

图片就会有明显的区分,如下:



猜你喜欢

转载自blog.csdn.net/qq_15969343/article/details/79841446
今日推荐