使用强度将图像转换为字符






4.60/5 (9投票s)
本文档展示了如何使用数字 1 和 0 来显示图像。
引言
主要思想是读取图像每个分组的强度值。(这里所说的分组是由相邻像素组成的矩阵。)然后写入数字 1 或 0,其颜色值是源分组的平均强度值。
背景
首先,我们需要区分强度值的获取方式。在本文中,我将展示两种方法:
- 第一种强度方法(提供更好的视觉效果):在这种方法中,强度值从分组的第一个像素获取。
- 平均强度方法:在这里,我们计算每个分组的平均强度值。
在两种方法中,获取强度值后,我们都会写入数字 1 或 0,其颜色值就是我们获取到的值。
上述机制应用于图像,通过将其读取为矩阵(二维数组)。注意,遍历数组的方式是“对于图像的每一行,访问每个像素”。
下图显示了两种方法之间的差异
![]() |
原始图像 |
![]() |
![]() |
第一种强度方法 | 平均强度方法 |
Using the Code
Tools
类using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace Image2Characters
{
public static class Tools
{
/// <summary>
/// folder names both input and output folder
/// </summary>
static String strImagesFolderName = "images";
static String strHtmlFolderName = "pages";
/// <summary>
/// Result html file content
/// </summary>
static String strHtmlFileHeader = "<html><head><title>{0} Image - {1}</title></head><body><pre><font><font style=\"font-size: 9px;\">";
static String strHtmlFileFooter = "</font></font></pre></body></html>";
/// <summary>
/// How many pixels fit in each group
/// here the group size is 12 * 5
/// </summary>
static int iWidthRatio = 5, iHeightRatio = 12;
/// <summary>
/// Make sure program needed directories is exists
/// </summary>
public static void InitEnviroment()
{
Directory.CreateDirectory(strImagesFolderName);
Directory.CreateDirectory(strHtmlFolderName);
}
/// <summary>
/// Calculates the Intensity of each given pixel
/// </summary>
/// <param name="color">the image pixel</param>
/// <returns>the Intensity</returns>
public static int GetIntensity(Color color)
{
return (int)(0.3f * color.R + 0.59f * color.G + 0.11f * color.B);
}
/// <summary>
/// Retrieves the available images that should be converted
/// </summary>
/// <returns></returns>
public static String[] GetImages()
{
return Directory.GetFiles(strImagesFolderName + @"\", "*.jpg");
}
/// <summary>
/// Converts a given image file to its matching html file
/// in "pages" folder using "1st Intensity" value
/// </summary>
/// <param name="strImageName">Image to be converted path</param>
public static void ConvertImageToCharacter1stIntensity(String strImageName)
{
Bitmap img = (Bitmap)Image.FromFile(strImageName);
String strDigit = ""
, strImageNameWithoutExtension = Path.GetFileNameWithoutExtension(strImageName);
StringBuilder createdFileContent = new StringBuilder();
int k = 0; // for switching between 1 and 0
createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);
// looping through the image
for (int i = 0; i < img.Height - 1; i += iHeightRatio)
{
for (int j = 0; j < img.Width - 1; j += iWidthRatio)
{
strDigit = (k % 2 == 0) ? "0" : "1";
k++;
createdFileContent.AppendFormat("<font color=\"#{0:x2}{0:x2}{0:x2}\">{1}</font>", Tools.GetIntensity(img.GetPixel(j, i)), strDigit);
}
createdFileContent.Append("<br/>");
}
createdFileContent.Append(strHtmlFileFooter);
// save html output file in "pages" folder
File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
}
/// <summary>
/// Converts a given image file to its matching html file
/// in "pages" folder using "Average Intensity" value
/// </summary>
/// <param name="strImageName">Image to be converted path</param>
public static void ConvertImageToCharacterAverageIntensity(String strImageName)
{
Bitmap img = (Bitmap)Image.FromFile(strImageName);
String strDigit = ""
, strImageNameWithoutExtension = Path.GetFileNameWithoutExtension(strImageName);
StringBuilder createdFileContent = new StringBuilder();
int iAverageValue // intensity average value for each group
, k = 0 // for switching between 1 and 0
, iItemsCountInSubMatrix = iWidthRatio * iHeightRatio // the count of elements in group
, iSubMatrixElementsSum; // the total value of group elements
createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);
// looping through the image
for (int i = 0; i < img.Height - 1; i += iHeightRatio)
{
for (int j = 0; j < img.Width - 1; j += iWidthRatio)
{
iSubMatrixElementsSum = 0;
// looping inside the group
for (int i2 = 0; i2 < iHeightRatio - 1; i2++)
{
if (i + i2 < img.Height)
{
for (int j2 = 0; j2 < iWidthRatio - 1; j2++)
{
if (j + j2 < img.Width)
{
iSubMatrixElementsSum += Tools.GetIntensity(img.GetPixel(j + j2, i + i2));
}
}
}
}
// calculating the average intensity value
iAverageValue = iSubMatrixElementsSum / iItemsCountInSubMatrix;
strDigit = (k % 2 == 0) ? "0" : "1";
k++;
createdFileContent.AppendFormat("<font color=\"#{0:x2}{0:x2}{0:x2}\">{1}</font>", iAverageValue, strDigit);
}
createdFileContent.Append("<br/>");
}
createdFileContent.Append(strHtmlFileFooter);
// save html output file in "pages" folder
File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
}
}
}
历史
- v1.0 15/10/08
注意事项
- 由于我的代码实现的原因,只有以“jpg”扩展名结尾的图像才被接受。
- 我选择的分组大小为 12 行和 5 列。如果您没有获得所需的结果,可以更改这些值。或者,您可以将其设置为 1 行和 1 列,这将把每个像素映射到一个数字;当然,这将生成更大的图像。
- 该项目使用 C# 2.0,但在 Visual Studio 2008 中编写。
- 我根据我的实际尝试编写了“第一种强度方法”,这意味着它不是参考性的,与“平均强度方法”相反,后者是一种简单且众所周知的方法。但我更喜欢编写“第一种强度方法”,因为它显示了更好的结果。
改进
- 将分组大小与源图像的大小相关联。 这种改进将减少源图像较小时出现不良结果的情况。 例如:宽度 = 80~110px。