// 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;
}
二值化及伽马调整的函数
最新推荐文章于 2023-04-02 20:37:12 发布