分段线性变换
分段线性变换也叫做灰度线性拉伸,常用的是分三段分线性变换。如下图:
图中对灰度区间[a,b]进行了扩展,而灰度区间[0, a]和[b, Mf]收到了压缩。通过细心调整折线拐点的位置及控制分段直线的斜率,可对任意灰度区间进行扩展和压缩。、本文就是基于这做的图像增强。
#include "cxcore.h"
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
#include <windows.h>
LARGE_INTEGER m_liPerfFreq;
LARGE_INTEGER m_liPerfStart;
LARGE_INTEGER liPerfNow;
double dfTim;
void getStartTime()
{
QueryPerformanceFrequency(&m_liPerfFreq);
QueryPerformanceCounter(&m_liPerfStart);
}
void getEndTime()
{
QueryPerformanceCounter(&liPerfNow);
dfTim=( ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000.0f)/m_liPerfFreq.QuadPart);
}
//定义折线变换的坐标
const CvPoint p1 = cvPoint(46, 0);
const CvPoint p2 = cvPoint(200, 255);
const bool showSteps = true;
const int NumVideo = 1;
using namespace cv;
int main(void)
{
CvCapture* capture;
IplImage* src;;
char *video_name = NULL;
video_name = (char*)malloc(50*sizeof(char));
for(int jj=1; jj<=NumVideo; jj++)
{
printf("处理第%d段视频\n",jj);
//读取d盘下video目录里的1.avi文件。
sprintf_s(video_name, 50, "D:\\video\\%d.avi",1);
capture = cvCaptureFromAVI(video_name);
if( capture == NULL )
{
printf("视频文件打开失败!!\n");
return -1;
}
//定义和初始化变量
src = cvQueryFrame(capture);
cvNamedWindow("source Image",CV_WINDOW_AUTOSIZE);
cvShowImage("source Image",src);}
for(int i=0;i<130;i++)
src = cvQueryFrame(capture); //获取一帧图片
while( 1 )
{
//获取空格键值,并置位抠图标志位flag
int c = cvWaitKey(0);
if((char)c==(char)32)
{
src = cvQueryFrame(capture); //获取一帧图片
//
image = imread("..\\image4\\test.bmp");
if(! src->imageData ) // Check for invalid input
{
printf("Could not open or find the image");
return -1;
}
//
char*filename="1 (1).bmp";
//
IplImage*src=cvLoadImage(filename,0);
IplImage* srcTemp = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
getStartTime();
if(src->nChannels == 3){
cvCvtColor(src,srcTemp,CV_BGR2GRAY);
}
cvSaveImage("test.bmp",src);
//
cvEqualizeHist(srcTemp,srcTemp);
//
IplImage*image=cvLoadImage(filename,0);
IplImage*image=cvCloneImage(srcTemp);
//----------************--------------------//
//显示处理前的图像的直方图
Mat resouce, dst;
/// Load image
resouce = Mat(src);
//
resouce = cvQueryFrame(capture);
if( !resouce.data )
{ return -1; }
/// Separate the image in 3 places ( B, G and R )
vector<Mat> bgr_planes;
split( resouce, bgr_planes );
/// Establish the number of bins
int histSize = 256;
/// Set the ranges ( for B,G,R) )
float range[] = { 0, 256 } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
Mat b_hist, g_hist, r_hist;
/// Compute the histograms:
calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
// Draw the histograms for B, G and R
int hist_w = 512; int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
/// Normalize the result to [ 0, histImage.rows ]
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
/// Draw for each channel
for( int i = 1; i < histSize; i++ )
{
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
}
/// Display
namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
imshow("calcHist Demo", histImage );
//-----------------------**************---------------------//
//对图像进行分段线性变化处理:
for( int y=0; y<image->height; y++ ) {
uchar* pDataSrc = (uchar*) (srcTemp->imageData + y * srcTemp->widthStep );
uchar* pDataImage = (uchar*) (image->imageData + y * image->widthStep );
for( int x=0; x<image->width; x++ ) {
if(pDataSrc[x]<=p1.x)
pDataImage[x]=(int)((p1.y/p1.x)*pDataSrc[x]);
else if(pDataSrc[x]>=p2.x)
//
pDataImage[x]=(int)((p2.y-p1.y)/(p2.x-p1.x)*pDataSrc[x])+p1.y;
pDataImage[x]=p1.y;
else
//
pDataImage[x]=(int)(p1.y);
pDataImage[x]=(int)((p2.y-p1.y)/(p2.x-p1.x)*pDataSrc[x])+p1.y;
if(pDataImage[x]>255)
pDataImage[x]=255;
}
}
//
cvNormalize(image,image,255,0,CV_C,NULL);
if(showSteps){
cvShowImage("source Image",src);}
if(showSteps){
cvNamedWindow("gray Image",CV_WINDOW_AUTOSIZE);
cvShowImage("gray Image",image);}
//threshold
IplImage* gray=cvCloneImage(image);
//
cvThreshold(image,gray,101,255,CV_THRESH_OTSU+CV_THRESH_BINARY);
int blockSize = 19;
int constValue = 3;
cvAdaptiveThreshold(image,gray,255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, blockSize, constValue);
cvSmooth(gray,gray,CV_MEDIAN,5);
if(showSteps){
cvNamedWindow("threshold Image",CV_WINDOW_AUTOSIZE);
cvShowImage("threshold Image",gray);}
getEndTime();
printf("%f\n",dfTim);
cvWaitKey(0);
}
}
cvWaitKey(0);
}