二值化及伽马调整的函数

17 篇文章 0 订阅
10 篇文章 0 订阅
// opencv medianblur.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <atlimage.h>
#include <opencv\cv.hpp>
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;
void CreatTable_Gamma(uchar table[],float nPercent)
{
	float val;
	for (int i = 0; i<256; i++)
	{
		val = pow((float)i / 255.0f, nPercent)*255.0f;
		if (val>255)
			val = 255;
		if (val<0)
			val = 0;
		table[i] = (uchar)val;
	}
}
void ImageAdjust(Mat src, uchar table[])//伽马调整
{

	int step = src.step; //相邻行的同列点之间的字节数
	int channels = src.channels(); //颜色通道数目(1,2,3,4)
	uchar* data = (uchar*)src.data;
	//intensity transform
	int x, y;
	int val;
	for (y = 0; y < src.rows; y++)
	{
		for (x = 0; x < src.cols; x++)
		{
			for (int k = 0; k != channels; ++k)
			{
				val = data[y*step + x*channels + k];
				data[y*step + x*channels + k] = table[val];
			}
		}
	}
}
void thresholdIntegral(cv::Mat &inputMat, cv::Mat &outputMat)//自定义二值化函数;
{
	// accept only char type matrices
	CV_Assert(!inputMat.empty());
	CV_Assert(inputMat.depth() == CV_8U);
	CV_Assert(inputMat.channels() == 1);
	CV_Assert(!outputMat.empty());
	CV_Assert(outputMat.depth() == CV_8U);
	CV_Assert(outputMat.channels() == 1);

	// rows -> height -> y
	int nRows = inputMat.rows;
	// cols -> width -> x
	int nCols = inputMat.cols;

	// create the integral image
	cv::Mat sumMat;
	cv::integral(inputMat, sumMat);
	Mat imageIntegral;
	normalize(sumMat, imageIntegral, 0, 255, CV_MINMAX);  //归一化,方便显示  
	Mat imageIntegralNorm;
	convertScaleAbs(imageIntegral, imageIntegralNorm); //精度转换为8位int整型 
	imshow("归一", imageIntegralNorm);
	CV_Assert(sumMat.depth() == CV_32S);
	CV_Assert(sizeof(int) == 4);

	int S = MAX(nRows, nCols) / 8;
	double T = 0.15;

	// perform thresholding
	int s2 = S / 2;
	int x1, y1, x2, y2, count, sum;

	// CV_Assert(sizeof(int) == 4);
	int *p_y1, *p_y2;
	uchar *p_inputMat, *p_outputMat;

	for (int i = 0; i < nRows; ++i)
	{
		y1 = i - s2;
		y2 = i + s2;

		if (y1 < 0){
			y1 = 0;
		}
		if (y2 >= nRows) {
			y2 = nRows - 1;
		}

		p_y1 = sumMat.ptr<int>(y1);
		p_y2 = sumMat.ptr<int>(y2);
		p_inputMat = inputMat.ptr<uchar>(i);
		p_outputMat = outputMat.ptr<uchar>(i);

		for (int j = 0; j < nCols; ++j)
		{
			// set the SxS region
			x1 = j - s2;
			x2 = j + s2;

			if (x1 < 0) {
				x1 = 0;
			}
			if (x2 >= nCols) {
				x2 = nCols - 1;
			}

			count = (x2 - x1)*(y2 - y1);

			// I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)
			sum = p_y2[x2] - p_y1[x2] - p_y2[x1] + p_y1[x1];

			if ((int)(p_inputMat[j] * count) < (int)(sum*(1.0 - T)))
				p_outputMat[j] = 255;
			else
				p_outputMat[j] = 0;
		}
	}
}
void CImageToMat(CImage& cimage, Mat& mat)
{
	if (true == cimage.IsNull())
	{
		return;
	}


	int nChannels = cimage.GetBPP() / 8;
	if ((1 != nChannels) && (3 != nChannels))
	{
		return;
	}
	int nWidth = cimage.GetWidth();
	int nHeight = cimage.GetHeight();


	//重建mat  
	if (1 == nChannels)
	{
		mat.create(nHeight, nWidth, CV_8UC1);
	}
	else if (3 == nChannels)
	{
		mat.create(nHeight, nWidth, CV_8UC3);
	}


	//拷贝数据  


	uchar* pucRow;                                  //指向数据区的行指针  
	uchar* pucImage = (uchar*)cimage.GetBits();     //指向数据区的指针  
	int nStep = cimage.GetPitch();                  //每行的字节数,注意这个返回值有正有负  


	for (int nRow = 0; nRow < nHeight; nRow++)
	{
		pucRow = (mat.ptr<uchar>(nRow));
		for (int nCol = 0; nCol < nWidth; nCol++)
		{
			if (1 == nChannels)
			{
				pucRow[nCol] = *(pucImage + nRow * nStep + nCol);
			}
			else if (3 == nChannels)
			{
				for (int nCha = 0; nCha < 3; nCha++)
				{
					pucRow[nCol * 3 + nCha] = *(pucImage + nRow * nStep + nCol * 3 + nCha);
				}
			}
		}
	}
}
CImage* get()
{
	CImage *my = new CImage;
	my->Load("d:/19.jpg");
	return my;
}
void salt(Mat& image, int n) {
	for (int k = 0; k<n; k++) {
		int i = rand() % image.cols;
		int j = rand() % image.rows;

		if (image.channels() == 1) {   //判断是一个通道
			image.at<uchar>(j, i) = 255;
		}
		else {
			image.at<cv::Vec3b>(j, i)[0] = 255;
			image.at<cv::Vec3b>(j, i)[1] = 255;
			image.at<cv::Vec3b>(j, i)[2] = 255;
		}
	}
}
void Sharpen(const Mat &image, Mat &result)//去椒盐
{
	result.create(image.size(), image.type());
	for (int j = 1; j<image.rows - 1; j++)
	{
		const uchar* previous = image.ptr<const uchar>(j - 1);
		const uchar* current = image.ptr<const uchar>(j);
		const uchar* next = image.ptr<const uchar>(j + 1);

		uchar * output = result.ptr<uchar>(j);
		for (int i = 1; i<(image.cols - 1); i++)
		{
			output[i * 3] = saturate_cast<uchar>(5 * current[i * 3] - current[(i - 1) * 3] - current[(i + 1) * 3] - previous[i * 3] - next[i * 3]);
			output[i * 3 + 1] = saturate_cast<uchar>(5 * current[i * 3 + 1] - current[(i - 1) * 3 + 1] - current[(i + 1) * 3 + 1] - previous[i * 3 + 1] - next[i * 3 + 1]);
			output[i * 3 + 2] = saturate_cast<uchar>(5 * current[i * 3 + 2] - current[(i - 1) * 3 + 2] - current[(i + 1) * 3 + 2] - previous[i * 3 + 2] - next[i * 3 + 2]);
		}
	}
	result.row(0).setTo(Scalar(0, 0, 0));
	result.row(result.rows - 1).setTo(Scalar(0, 0, 0));
	result.col(0).setTo(Scalar(0, 0, 0));
	result.col(result.cols - 1).setTo(Scalar(0, 0, 0));
}
void SharpenKernel(const Mat &image, Mat &result)
{
	Mat kernel(3, 3, CV_32F, Scalar(0));
	kernel.at<float>(1, 1) = 5;
	kernel.at<float>(0, 1) = -1;
	kernel.at<float>(2, 1) = -1;
	kernel.at<float>(1, 0) = -1;
	kernel.at<float>(1, 2) = -1;
	filter2D(image, result, image.depth(), kernel);
	result.row(0).setTo(Scalar(0, 0, 0));
	result.row(result.rows - 1).setTo(Scalar(0, 0, 0));
	result.col(0).setTo(Scalar(0, 0, 0));
	result.col(result.cols - 1).setTo(Scalar(0, 0, 0));
}
int main()
{
	Mat src = imread("d:\\19.jpg");
	resize(src, src, Size(src.cols/2, src.rows / 2));
	imshow("原图", src);
	Mat gm = src.clone();
	uchar table[256];
	CreatTable_Gamma(table, 2);
	ImageAdjust(gm, table);
	imshow("gm", gm);

	//Mat dst;
	//medianBlur(gm, dst, 3);
	//imshow("中值去噪", dst);
	Mat gray;
	cvtColor(gm, gray, CV_RGB2GRAY);
	Mat xx1 = gray.clone();
	thresholdIntegral(xx1, xx1);
	imshow("自己二值", ~xx1);
	waitKey(0);
	Mat halfsize(src, Rect(0, 40, src.cols/2-10, src.rows-40));
	imwrite("d:\\1\\half.jpg", halfsize);
	salt(src, 20000);
	//imshow("原图", src);
	//Mat gray2;
	//cvtColor(src, gray2, CV_RGB2GRAY);
	//Mat xx1 = gray2.clone();
	//GaussianBlur(xx1, xx1, Size(13, 13), 2,2);
	//imshow("GS", ~xx1);
	//thresholdIntegral(gray2, xx1);
	//Mat xx2 = xx1.clone();
	//SharpenKernel(xx1, xx2);
	//imshow("xx2", ~xx2);
	//SharpenKernel(xx2, xx2);
	//imshow("锐化后原图xx", xx2);
	//Mat dst = src.clone();
	medianBlur(src, dst, 3);
	medianBlur(dst, dst, 3);
	//Mat hs;
	//SharpenKernel(dst, hs);
	//imshow("函数锐化", hs);
	//Mat sd;
	//Sharpen(dst, sd);
	medianBlur(dst, dst, 3);
	medianBlur(dst, dst, 3);
	medianBlur(dst, dst, 3);
	//imshow("手动锐化后", sd);
	//Mat gray1;
	//cvtColor(sd, gray1, CV_RGB2GRAY);
	//imshow("手动灰度", gray1);
	//Mat bw1;
	threshold(gray1, bw1, 100, 255, 0);
	//adaptiveThreshold(gray1, bw1, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 17, 0);
	//imshow("手动自适应二值化", bw1);
	//Mat xx=gray1.clone();
	//thresholdIntegral(gray1, xx);
	//imshow("xx", ~xx);
	//Mat imageGamma(dst.size(), CV_32FC3);
	//for (int i = 0; i < dst.rows; i++)
	//{
	//	for (int j = 0; j < dst.cols; j++)
	//	{
	//		imageGamma.at<Vec3f>(i, j)[0] = (dst.at<Vec3b>(i, j)[0])*(dst.at<Vec3b>(i, j)[0])*(dst.at<Vec3b>(i, j)[0]);
	//		imageGamma.at<Vec3f>(i, j)[1] = (dst.at<Vec3b>(i, j)[1])*(dst.at<Vec3b>(i, j)[1])*(dst.at<Vec3b>(i, j)[1]);
	//		imageGamma.at<Vec3f>(i, j)[2] = (dst.at<Vec3b>(i, j)[2])*(dst.at<Vec3b>(i, j)[2])*(dst.at<Vec3b>(i, j)[2]);
	//	}
	//}
	归一化到0~255    
	//normalize(imageGamma, imageGamma, 0, 255, CV_MINMAX);
	转换成8bit图像显示    
	//convertScaleAbs(imageGamma, imageGamma);
	//imshow("伽马变换图像增强效果", imageGamma);
	//Mat gray;
	//cvtColor(imageGamma, gray, CV_RGB2GRAY);
	//imshow("Gamma灰度", gray);
	Mat bw;
	//threshold(gray, bw, 100, 255, 0);
	adaptiveThreshold(gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 17, 0);
	imshow("伽马自适应二值化", bw);
	//Mat xy=gray.clone();
	//thresholdIntegral(gray, xy);
	//imshow("伽马自己二值化", xy);
	CImage *p = get();
	Mat m;
	CImageToMat(*p, m);
	imshow("原图", m);
	CImageDC srcDC(*p);
	CImage dst2;
	dst2.Create(p->GetWidth() * 2, p->GetHeight() * 2, 24);
	CImageDC dstDC(dst2);
	SetStretchBltMode(dstDC, HALFTONE);
	StretchBlt(dstDC, 0, 0, p->GetWidth() * 2, p->GetHeight() * 2, srcDC, 0, 0, p->GetWidth(), p->GetHeight(), SRCCOPY);
	Mat n;
	CImageToMat(dst2, n);
	imshow("放大后", n);
	



	waitKey(0);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值