图像处理:图片二值化学习,以及代码中如何实现

这篇具有很好参考价值的文章主要介绍了图像处理:图片二值化学习,以及代码中如何实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、了解下图片二值化的含义

2、进行图像二值化处理的方法

3、如何选择合适的阈值进行二值化

4、实现图片二值化(代码)

(1)是使用C++和OpenCV库实现:

(2)纯C++代码实现,不要借助其他库

(3)图片处理的一个实例:


1、了解下图片二值化的含义

(1)图片二值化是一种图像处理技术,它将彩色或灰度图像转换为只包含两个颜色的图像,通常是黑色和白色。这种转换是通过将图像中的每个像素的灰度值与一个阈值进行比较来实现的。

(2)在二值化过程中,如果像素的灰度值大于或等于阈值,则将该像素设置为白色(或亮色),否则将其设置为黑色(或暗色)。这样,图像中的每个像素都被映射到黑色或白色之一,从而产生了一个只有两种颜色的二值图像。

(3)二值化可以用于很多应用,例如文字识别、图像分割、形状检测等。通过将图像转换为二值图像,可以突出显示目标物体的轮廓和特征,并简化后续的图像处理任务。

2、进行图像二值化处理的方法

进行图像二值化处理的方法有多种,下面介绍两种常用的方法:

(1)全局阈值法(Global Thresholding):

        该方法假设整个图像的前景和背景具有明显的灰度差异,并且通过选择一个全局阈值来将图像分为两个部分。

具体步骤如下:

        1)将彩色或灰度图像转换为灰度图像。

        2)选择一个合适的全局阈值。

        3)遍历图像中的每个像素,如果像素的灰度值大于等于阈值,则将其设置为白色;否则将其设置为黑色。

(2)自适应阈值法(Adaptive Thresholding):

        该方法考虑到图像不同区域的光照条件可能不同,因此使用局部阈值来对图像进行分割。

具体步骤如下:

        1)将彩色或灰度图像转换为灰度图像。

        2)将图像分成多个小的局部区域。

        3)对每个局部区域计算一个适应性阈值。

        4)遍历图像中的每个像素,根据所在的局部区域的阈值将像素设置为黑色或白色。

这些方法可以使用图像处理库或软件实现,例如OpenCV、Python的PIL库等。具体的实现方式和参数选择会根据具体的图像和需求而有所不同。

3、如何选择合适的阈值进行二值化

选择合适的阈值进行图像二值化是一个关键的步骤,下面介绍几种常用的阈值选择方法:

(1)固定阈值法(Fixed Thresholding):该方法是最简单的阈值选择方法,直接根据经验或试验确定一个固定的阈值。例如,将阈值设为128,即大于等于128的像素设置为白色,小于128的像素设置为黑色。

(2)Otsu's 阈值法:Otsu's 阈值法是一种自动选择阈值的方法,它能够找到一个最佳的阈值,使得分割后的图像类间方差最大化。这种方法适用于具有双峰直方图的图像,其中前景和背景的灰度值分布明显不同。

(3)自适应阈值法(Adaptive Thresholding):自适应阈值法根据图像局部区域的灰度特性来选择阈值。它将图像分成多个小的局部区域,并对每个区域计算一个适应性阈值。这种方法适用于光照条件不均匀的图像。

(4)大津法与自适应阈值法的结合:有时候可以结合使用大津法和自适应阈值法,先使用大津法确定一个全局阈值,然后再使用自适应阈值法对图像进行细分割。

选择合适的阈值方法取决于图像的特性和需求。一般来说,如果图像具有明显的前景和背景差异,固定阈值法可能是一个简单有效的选择。如果图像的灰度分布复杂或光照条件不均匀,可以考虑使用自适应阈值法或Otsu's 阈值法。

4、实现图片二值化(代码)

(1)是使用C++和OpenCV库实现:

#include <opencv2/opencv.hpp>

int main() 
{
    // 读取图像
    cv::Mat image = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);

    // 检查图像是否成功读取
    if (image.empty()) {
        std::cout << "无法读取图像文件" << std::endl;
        return -1;
    }

    // 应用全局阈值法进行二值化
    cv::Mat binaryImage;
    double thresholdValue = 128; // 阈值设为128

    double maxValue = 255; // 最大值设为255

    cv::threshold(image, binaryImage, thresholdValue, maxValue, cv::THRESH_BINARY);

    // 显示原始图像和二值化后的图像
    cv::imshow("Original Image", image);
    cv::imshow("Binary Image", binaryImage);
    cv::waitKey(0);

    return 0;
}
(2)纯C++代码实现,不要借助其他库

#include <iostream>
#include <fstream>

#pragma pack(push, 1)
struct BMPHeader {
	char signature[2];
	int fileSize;
	int reserved;
	int dataOffset;
	int headerSize;
	int width;
	int height;
	short planes;
	short bitsPerPixel;
	int compression;
	int imageSize;
	int xPixelsPerMeter;
	int yPixelsPerMeter;
	int colorsUsed;
	int importantColors;
};
#pragma pack(pop)

bool Bmp2Binarization()
{
	// 读取BMP文件头信息
	ifstream file(("oldBmp.bmp"), std::ios::binary);

	if (!file) {
		cout << "无法打开BMP文件" << endl;
		return -1;
	}

	BMPHeader header;
	file.read(reinterpret_cast<char*>(&header), sizeof(BMPHeader));

	// 检查文件是否为24位真彩色BMP图像
	if (header.signature[0] != 'B' || header.signature[1] != 'M') {
		cout << "不支持的BMP文件格式" << endl;
		return -1;
	}

	if (header.bitsPerPixel != 24) {
		cout << "不支持的像素位数" << endl;
		return -1;
	}

	// 计算图像数据的行字节数
	int rowSize = ((header.width * 3 + 3) / 4) * 4;

	// 创建存储图像数据的数组
	unsigned char* image_data = new unsigned char[rowSize * header.height];

	// 读取图像数据
	file.read(reinterpret_cast<char*>(image_data), rowSize * header.height);

	// 关闭文件
	file.close();

	// 图像二值化处理
	int threshold_value = 128; // 设定阈值


	for (int y = 0; y < header.height; y++) {
		for (int x = 0; x < header.width; x++) {
			int index = y * rowSize + x * 3;
			unsigned char r = image_data[index + 2];
			unsigned char g = image_data[index + 1];
			unsigned char b = image_data[index];

			unsigned char gray = static_cast<unsigned char>(0.299 * r + 0.587 * g + 0.114 * b);

			if (gray > threshold_value) {
				image_data[index + 2] = 255;
				image_data[index + 1] = 255;
				image_data[index] = 255;
			}
			else {
				image_data[index + 2] = 0;
				image_data[index + 1] = 0;
				image_data[index] = 0;
			}
		}
	}

	// 保存二值化后的图像数据
	ofstream output_file("binary_image.bmp", ios::binary);

	if (!output_file) {
		cout << "无法保存二值化图像文件" << endl;
		delete[] image_data;
		return -1;
	}

	std::cout << "成功保存图像文件" << std::endl;
	output_file.write(reinterpret_cast<char*>(&header), sizeof(BMPHeader));
	output_file.write(reinterpret_cast<char*>(image_data), rowSize * header.height);

	// 关闭文件
	output_file.close();

	// 释放内存
	delete[] image_data;

	return 0;
}

在上述代码中,我们使用C++的文件输入输出流来读取和保存图像文件。首先,我们读取图像的头信息,并根据宽度和高度计算图像数据的大小。然后,我们分配内存并读取彩色图像数据。接下来,我们将彩色图像转换为灰度图像,通过对每个像素的RGB值求平均来计算灰度值。最后,我们应用阈值进行二值化处理,将灰度值大于等于阈值的像素设置为白色(255),小于阈值的像素设置为黑色(0)。最后,我们保存二值化后的图像。

请注意,上述代码假设输入图像为24位位图(BMP)格式,并且图像文件名为"input.bmp"。你可以根据实际情况修改文件名和图像格式。此外,该代码只适用于处理较小的图像,如果要处理更大的图像,可能需要优化内存使用和读写操作。

(3)jpg图片转化为二值化(纯C++,没有依赖opencv相关的库)

#include <iostream>
#include <fstream>

#pragma pack(push, 1)
struct JPGHeader {
	unsigned short marker;
	unsigned short length;
};

struct SOF0Segment {
	unsigned char precision;
	unsigned short height;
	unsigned short width;
	unsigned char numComponents;
};

struct Component {
	unsigned char id;
	unsigned char samplingFactors;
	unsigned char quantizationTableId;
};

struct DQTSegment {
	unsigned char tableInfo;
	unsigned char quantizationTable[64];
};

struct SOSegment {
	unsigned char numComponents;
	Component components[3];
};

#pragma pack(pop)

bool Jpg2Binarization() 
{
	// 读取JPEG文件
	ifstream file("image.jpg", ios::binary);
	if (!file) {
		cout << "无法打开JPEG文件" << endl;
		return -1;
	}

	// 读取JPEG头信息
	JPGHeader header;
	file.read(reinterpret_cast<char*>(&header), sizeof(JPGHeader));

	if (header.marker != 0xFFD8) {
		cout << "不支持的JPEG文件格式" << endl;
		return -1;
	}

	// 找到SOF0段
	SOF0Segment sof0;
	while (true) {
		file.read(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
		if (header.marker == 0xFFC0) {
			file.read(reinterpret_cast<char*>(&sof0), sizeof(SOF0Segment));
			break;
		}
		else {
			file.seekg(header.length - 2, ios::cur);
		}
	}

	// 检查图像是否为灰度图像
	if (sof0.numComponents != 1) {
		cout << "不支持的JPEG图像格式" << endl;
		return -1;
	}

	// 找到DQT段
	DQTSegment dqt;
	while (true) {
		file.read(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
		if (header.marker == 0xFFDB) {
			file.read(reinterpret_cast<char*>(&dqt), sizeof(DQTSegment));
			break;
		}
		else {
			file.seekg(header.length - 2, ios::cur);
		}
	}

	// 找到SOS段
	SOSegment sos;
	while (true) {
		file.read(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
		if (header.marker == 0xFFDA) {
			file.read(reinterpret_cast<char*>(&sos), sizeof(SOSegment));
			break;
		}
		else {
			file.seekg(header.length - 2, ios::cur);
		}
	}

	// 计算图像数据的宽度和高度
	int width = sof0.width;
	int height = sof0.height;

	// 创建存储图像数据的数组
	unsigned char* image_data = new unsigned char[width * height];

	// 读取图像数据
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			unsigned char value;
			file.read(reinterpret_cast<char*>(&value), sizeof(unsigned char));
			image_data[y * width + x] = value;
		}
	}

	// 关闭文件
	file.close();

	// 图像二值化处理
	int threshold_value = 128; // 设定阈值


	for (int i = 0; i < width * height; i++) {
		if (image_data[i] > threshold_value) {
			image_data[i] = 255;
		}
		else {
			image_data[i] = 0;
		}
	}

	// 保存二值化后的图像数据
	ofstream output_file("binary_image.jpg", ios::binary);
	if (!output_file) {
		cout << "无法保存二值化图像文件" << endl;
		delete[] image_data;
		return -1;
	}

	// 写入JPEG头信息
	output_file.write(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
	output_file.write(reinterpret_cast<char*>(&sof0), sizeof(SOF0Segment));

	// 写入DQT段
	output_file.write(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
	output_file.write(reinterpret_cast<char*>(&dqt), sizeof(DQTSegment));

	// 写入SOS段
	output_file.write(reinterpret_cast<char*>(&header), sizeof(JPGHeader));
	output_file.write(reinterpret_cast<char*>(&sos), sizeof(SOSegment));

	// 写入图像数据
	for (int y = 0; y < height; y++) {
		for (int x = 0; x < width; x++) {
			unsigned char value = image_data[y * width + x];
			output_file.write(reinterpret_cast<char*>(&value), sizeof(unsigned char));
		}
	}

	// 关闭文件
	output_file.close();

	// 释放内存
	delete[] image_data;

	return 0;
}
(3)图片处理的一个实例:

        1)jpg通过opencv转化为二值化图片,并生成新的jpg图片;

        2)读取图片数据,重新生成jpg图片;文章来源地址https://www.toymoban.com/news/detail-740085.html

#include <opencv2/opencv.hpp>
#include <iostream>

void binarizeJpeg(const std::string& inputFilename, const std::string& outputFilename, int threshold)
{
    // 1、jpg图片,转为二值化图片

	// 读取JPG文件
	cv::Mat jpgImage = cv::imread(inputFilename);

	// 转换为灰度图像
	cv::Mat grayImage;
	cv::cvtColor(jpgImage, grayImage, cv::COLOR_BGR2GRAY);

	// 二值化处理
	cv::Mat binaryImage;
	cv::threshold(grayImage, binaryImage, threshold, 255, cv::THRESH_BINARY);

	// 保存为JPG文件
	cv::imwrite(outputFilename, binaryImage);



    // 2、读取jpg图片数据出来,重新生成新的图片

	unsigned char * hJpegBuf = NULL;//存储原本jpg格式的文件数据
	DWORD      JpegBufSize;
	FILE*      hfjpg;//打开原本jpg格式的文件
	errno_t err = fopen_s(&hfjpg, outputFilename.c_str(), "rb");//正确返回0,不正确返回非0
	if (err != 0)
	{
		printf("文件打开失败\n");
	}

	fseek(hfjpg, 0L, SEEK_END);
	JpegBufSize = ftell(hfjpg);
	fseek(hfjpg, 0L, SEEK_SET);
	hJpegBuf = new unsigned char[JpegBufSize];

	fread(hJpegBuf, sizeof(char), JpegBufSize, hfjpg);
	fclose(hfjpg);

	FILE* file = fopen("\\small_new.jpg").c_str(), "wb");
	fwrite(hJpegBuf, 1, JpegBufSize, file);
	fclose(file);
}



// 调用
binarizeJpeg("\\small.jpg", "\\small_Binary.jpg", 128);

到了这里,关于图像处理:图片二值化学习,以及代码中如何实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图像处理(二值图、灰度图、彩色图像)

    图像处理之二值图像、灰度图像、RGB图像 1、二值图像 定义:二值图像是值仅仅包含黑色和白色的图像 计算机在处理时,会把黑色像素点处理为0,白色像素点处理1。由于只用一个比特位就能表示,所以称之为二值图像。 2、灰度图 为了表达更丰富的颜色细节,灰度图采用更

    2024年02月06日
    浏览(61)
  • [2] 图像处理之----二值化处理

    简单阈值是选取一个全局阈值,然后把整幅图像分成非黑即白的二值图像,灰度值大于阈值就赋为255反之为0。 ret,mask = cv2.threshold(img2gray,175,255,cv2.THRESH_BINAR) 返回值一: 阈值,(Otsu‘s二值化会用到) 返回值二: 处理以后的图像 参数一: 初始图像 参数二:我们自己设定的阈

    2024年02月05日
    浏览(56)
  • OpenCV图像处理----图像的二值化

    图像二值化( Image Binarization) 就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。 二值化的原理 OpenCV提供的图像二值化API threshold()方法参数: 图片矩阵 阈值 图片中的最大值 二值化的方式 二值化的方式: THRESH_BINARY 高于阈值改为

    2024年02月12日
    浏览(42)
  • MATLAB图像处理(二):图像转二值图

    二值图即黑白图,图中只有黑白色之分。图像的二维矩阵只由0和1构成,0表黑色,1表白色。 二值化利于图像进一步处理,且数据量减小,易于凸显出目标轮廓。 具体定义可以参考如下链接: http://zhidao.baidu.com/question/89536354.html 首先对有256个亮度等级的灰度图像进行阈值选取

    2024年02月04日
    浏览(53)
  • matlab数字图像处理——图像的读写,灰度、二值图像

    一、实验目的 1.结合数字图像处理的知识,直观感受图像处理的基本实现过程 2.熟悉MATLAB工具的使用 3.了解图像的读写和显示 二、实验内容 实验内容一:图像读取 (1)利用编程实现读取图像 利用imread读取文件夹images中的图像;查看读取到的图像数据矩阵,对比灰度图像、

    2024年02月07日
    浏览(58)
  • 【OpenCV】 基础入门(二)图像基础概念 | 图像灰度化处理 | 图像二值化处理

      在计算机中用一般用 M x N 的矩阵来表示一幅尺寸大小为 M x N 的数字图像,矩阵元素的值就是该图像对应位置上的像素值。    对于计算机本地磁盘中的彩色图像,单机鼠标右键,选择“属性”,可以看到一幅图像的基本信息。 1、灰度图:   灰度图是每个像素只有一

    2024年04月14日
    浏览(51)
  • 基于opencv的c++图像处理(图像二值化)

    基于opencv的c++接口,实现常用的图像二值化方法,包括了最大类间方差法(OTSU)、固定化阈值以及自适应阈值。 该函数将固定级别的阈值应用于多通道阵列。该函数通常用于从灰度图像中获取双层(二进制)图像(#compare 也可用于此目的)或用于去除噪声,即过滤掉值过小

    2024年02月07日
    浏览(51)
  • python图像处理实战(二)—二值化图像与线性变换

    🚀写在前面🚀 🖊个人主页:https://blog.csdn.net/m0_52051577?type=blog  🎁欢迎各位大佬支持点赞收藏,三连必回!! 🔈本人新开系列专栏—python图像处理 ❀愿每一个骤雨初晴之时,所有的蜻蜓振翅和雨后惊雷,都归你。 前言         首先引入以下灰度变换的概念。      

    2024年02月07日
    浏览(52)
  • OpenCV常用功能——灰度处理和图像二值化处理

    1.1 cvtColor函数 函数原型: 功能 :转换图像颜色空间。 参数 : src: 输入图像。 code: 颜色空间转换代码。可以取常量cv2.COLOR_BGR2GRAY或cv2.COLOR_RGB2GRAY。 dst: 输出图像。 dstCn: 输出图像的通道数,如果设置为0,则跟随转换代码自动设置。 内置函数示例代码: 灰度处理的原理是将

    2024年02月08日
    浏览(62)
  • FPGA|数字图像处理实现口罩识别——二值化

    【写在前面】刚入门小菜鸟,记录一下口罩识别学习过程。参考文件和网址会在文末注明。有错误欢迎指出,也欢迎进行补充~ 原理图如下,二值化对应为红框里的部分 使用的二值化方法是 手动指定一个 阈值 ,通过阈值来进行二值化处理 。(还有一种方法是一个自适应阈值

    2023年04月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包