【编程语言】利用CImage类对图像像素的处理(图像二值化)

    最近做的课程作业需要用到CImage函数处理图像,其中涉及到读取图像以及对图像像素进行操作,在这里记录一下自己的理解。


    首先是CImage类的定义和读取图片

	CImage srcImage;
	CImage dstImage;
	CString path = "C:\\Users\\Administrator\\Desktop\\阈值分割_20172120658\\input.png";
	CString pathdown = "C:\\Users\\Administrator\\Desktop\\阈值分割_20172120658\\outtput.png";

    如图 定义两个CImage类的对象,然后使用CString类型的变量定义图片的读取路径和保存路径。

	srcImage.Load(path);

	byte* pRealData; 

    这里利用CImage::Load()函数读取图片到srcImage中,接下来准备读取图像中的像素值,因为在CImage中利用堆栈进行读取的方法速度很慢,在这里我就不写了,这里使用的是直接利用c里面的指针对像素进行读取和遍历操作。首先定义一个byte类型的指针。

	pRealData = (byte*)srcImage.GetBits();	//获取到图片内存点的位置

	int pit = srcImage.GetPitch();			//图像每行字节数

	int bitCount = srcImage.GetBPP() / 8;	//获取每像素的位数~~/8得到字节数

	cout << "图像每行的字节数" << pit << " " << "图像每个像素的位数" << bitCount << endl;

    利用CImage::GetBits()函数获取图片内存点的位置,使用这种方法的时候,需要考虑图形的结构,使用CImage::GetBPP获取每个像素点占几位,还需要使用CImage::GetPitch获取每一行位的个数,根据GetPitch的正负值来判定GetBits获取到的head是首行的还是尾行的。负值即为尾部,正值即为头部。

    

    其中pit得到的是字节数,也就是说如果每个像素有3个字节(RGB),一个宽为100像素的图片它的CImage::GetPitch()就是300。CImage::GetBPP()得到的是每个像素的位数,通常灰度图为8或者32,三通道RGB图像为24位。


	int height = srcImage.GetHeight();
	int width = srcImage.GetWidth();

	cout << "height" << height << "   width" << width << endl;


	vector<int> gray(256);
	for (int i = 1; i <= 256; i++)
	{
		gray.push_back(0);
	}

	
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			gray.at((int)(*(pRealData + pit*i + j*bitCount))) += 1;
		}

	}

对图像的像素进行读取,需要对指针进行转换,转换为int类型。我这里是对图像的灰度值进行了统计处理。



最后附上一个利用直方图做的图像二值化

#include<atlimage.h>
#include<stdio.h>
#include<iostream>
#include<vector>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;


void main()
{
	CImage srcImage;
	CImage dstImage;
	CString path = "C:\\Users\\Administrator\\Desktop\\阈值分割_20172120658\\input.png";
	CString pathdown = "C:\\Users\\Administrator\\Desktop\\阈值分割_20172120658\\outtput.png";

	srcImage.Load(path);

	byte* pRealData; 
	byte* pRealData1; 
	byte* pRealData2; 
	byte* pRealData3;
	pRealData = (byte*)srcImage.GetBits();	//获取到图片内存点的位置

	int pit = srcImage.GetPitch();			//图像每行字节数

	int bitCount = srcImage.GetBPP() / 8;	//获取每像素的位数~~/8得到字节数

	cout << "图像每行的字节数" << pit << " " << "图像每个像素的位数" << bitCount << endl;

	int height = srcImage.GetHeight();
	int width = srcImage.GetWidth();

	cout << "height" << height << "   width" << width << endl;


	vector<int> gray(256);
	for (int i = 1; i <= 256; i++)
	{
		gray.push_back(0);
	}
	//pRealData1 = pRealData;
	
	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			gray.at((int)(*(pRealData + pit*i + j*bitCount))) += 1;
		}

	}
	int max = 0;
	int sec = 0;
	int locamax = 0;
	int locasec = 0;

	for (int i = 0; i < 256; i++)
	{
		cout << i << "---" << gray[i] << endl;
		if (gray[i] > max)
		{
			max = gray[i];
			locamax = i;        //获取相同灰度值像素点最多的灰度值
		}
	}
	for (int i = 0; i < 256; i++)
	{
		
		if (gray[i] > sec&&abs(i-locamax)>10)    //第二多的点需要距离最多的点至少10个灰度单位
		{
			sec = gray[i];
			locasec = i;     //获取相同灰度值像素点第二多的灰度值

		}
	}

	cout <<locamax<<"__"<<locasec << endl;
	
	int min = (locamax + locasec) / 2;    //取两峰中间值作为二值化分割阈值

	for (int i = 0; i < height; i++)
	{
		for (int j = 0; j < width; j++)
		{
			if ((int)(*(pRealData + pit*i + j*bitCount)) < min)
			{
				*(pRealData + pit*i + j*bitCount) = 0;
				*(pRealData + pit*i + j*bitCount+1) = 0;
				*(pRealData + pit*i + j*bitCount+2) = 0;
			}
			else
			{
				*(pRealData + pit*i + j*bitCount) = 255;
				*(pRealData + pit*i + j*bitCount + 1) = 255;
				*(pRealData + pit*i + j*bitCount + 2) = 255;
			}

		}

	}


	srcImage.Save(pathdown);

	system("pause");
}

                                                原图

                                             二值化
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值