两组图像:左边较暗,右边较亮
第一行是原图像,他们下面是用四种算法处理的结果
依次为:
1.一种混合算法
2.msr,multi-scale retinex
3.msrcr,multi-scale retinex with color restoration
4.ssr,single scale retinex
源码,retinex算法的三种,其源码是国外一个研究生的毕设项目
头文件:
/* * Copyright (c) 2006, Douglas Gray ([email protected], [email protected]) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the <organization> nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Douglas Gray ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "cv.h" extern double* CreateKernel(double sigma); extern int* CreateFastKernel(double sigma); extern void FilterGaussian(IplImage* img, double sigma); extern void FastFilter(IplImage *img, double sigma); extern void Retinex (IplImage *img, double sigma, int gain = 128, int offset = 128); extern void MultiScaleRetinex (IplImage *img, int scales, double *weights, double *sigmas, int gain = 128, int offset = 128); extern void MultiScaleRetinexCR (IplImage *img, int scales, double *weights, double *sigmas, int gain = 128, int offset = 128, double restoration_factor = 6, double color_gain = 2);
实现:
/* * Copyright (c) 2006, Douglas Gray ([email protected], [email protected]) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the <organization> nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Douglas Gray ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "retinex.h" #include <math.h> //#define USE_EXACT_SIGMA #define pc(image, x, y, c) image->imageData[(image->widthStep * y) + (image->nChannels * x) + c] #define INT_PREC 1024.0 #define INT_PREC_BITS 10 inline double int2double(int x) { return (double)x / INT_PREC; } inline int double2int(double x) { return (int)(x * INT_PREC + 0.5); } inline int int2smallint(int x) { return (x >> INT_PREC_BITS); } inline int int2bigint(int x) { return (x << INT_PREC_BITS); } // // CreateKernel // // Summary: // Creates a normalized 1 dimensional gaussian kernel. // // Arguments: // sigma - the standard deviation of the gaussian kernel. // // Returns: // double* - an array of values of length ((6*sigma)/2) * 2 + 1. // // Note: // Caller is responsable for deleting the kernel. // double* CreateKernel(double sigma) { int i, x, filter_size; double* filter; double sum; // Reject unreasonable demands if ( sigma > 200 ) sigma = 200; // get needed filter size (enforce oddness) filter_size = (int)floor(sigma*6) / 2; filter_size = filter_size * 2 + 1; // Allocate kernel space filter = new double[filter_size]; // Calculate exponential sum = 0; for (i = 0; i < filter_size; i++) { x = i - (filter_size / 2); filter[i] = exp( -(x*x) / (2*sigma*sigma) ); sum += filter[i]; } // Normalize for (i = 0, x; i < filter_size; i++) filter[i] /= sum; return filter; } // // CreateFastKernel // // Summary: // Creates a faster gaussian kernal using integers that // approximate floating point (leftshifted by 8 bits) // // Arguments: // sigma - the standard deviation of the gaussian kernel. // // Returns: // int* - an array of values of length ((6*sigma)/2) * 2 + 1. // // Note: // Caller is responsable for deleting the kernel. // int* CreateFastKernel(double sigma) { double* fp_kernel; int* kernel; int i, filter_size; // Reject unreasonable demands if ( sigma > 200 ) sigma = 200; // get needed filter size (enforce oddness) filter_size = (int)floor(sigma*6) / 2; filter_size = filter_size * 2 + 1; // Allocate kernel space kernel = new int[filter_size]; fp_kernel = CreateKernel(sigma); for (i = 0; i < filter_size; i++) kernel[i] = double2int(fp_kernel[i]); delete fp_kernel; return kernel; } // // FilterGaussian // // Summary: // Performs a gaussian convolution for a value of sigma that is equal // in both directions. // // Arguments: // img - the image to be filtered in place. // sigma - the standard deviation of the gaussian kernel to use. // void FilterGaussian(IplImage* img, double sigma) { int i, j, k, source, filter_size; int* kernel; IplImage* temp; int v1, v2, v3; // Reject unreasonable demands if ( sigma > 200 ) sigma = 200; // get needed filter size (enforce oddness) filter_size = (int)floor(sigma*6) / 2; filter_size = filter_size * 2 + 1; kernel = CreateFastKernel(sigma); temp = cvCreateImage(cvSize(img->width, img->height), img->depth, img->nChannels); // filter x axis for (j = 0; j < temp->height; j++) for (i = 0; i < temp->width; i++) { // inner loop has been unrolled v1 = v2 = v3 = 0; for (k = 0; k < filter_size; k++) { source = i + filter_size / 2 - k; if (source < 0) source *= -1; if (source > img->width - 1) source = 2*(img->width - 1) - source; v1 += kernel[k] * (unsigned char)pc(img, source, j, 0); if (img->nChannels == 1) continue; v2 += kernel[k] * (unsigned char)pc(img, source, j, 1); v3 += kernel[k] * (unsigned char)pc(img, source, j, 2); } // set value and move on pc(temp, i, j, 0) = (char)int2smallint(v1); if (img->nChannels == 1) continue; pc(temp, i, j, 1) = (char)int2smallint(v2); pc(temp, i, j, 2) = (char)int2smallint(v3); } // filter y axis for (j = 0; j < img->height; j++) for (i = 0; i < img->width; i++) { v1 = v2 = v3 = 0; for (k = 0; k < filter_size; k++) { source = j + filter_size / 2 - k; if (source < 0) source *= -1; if (source > temp->height - 1) source = 2*(temp->height - 1) - source; v1 += kernel[k] * (unsigned char)pc(temp, i, source, 0); if (img->nChannels == 1) continue; v2 += kernel[k] * (unsigned char)pc(temp, i, source, 1); v3 += kernel[k] * (unsigned char)pc(temp, i, source, 2); } // set value and move on pc(img, i, j, 0) = (char)int2smallint(v1); if (img->nChannels == 1) continue; pc(img, i, j, 1) = (char)int2smallint(v2); pc(img, i, j, 2) = (char)int2smallint(v3); } cvReleaseImage( &temp ); delete kernel; } // // FastFilter // // Summary: // Performs gaussian convolution of any size sigma very fast by using // both image pyramids and seperable filters. Recursion is used. // // Arguments: // img - an IplImage to be filtered in place. // void FastFilter(IplImage *img, double sigma) { int filter_size; // Reject unreasonable demands if ( sigma > 200 ) sigma = 200; // get needed filter size (enforce oddness) filter_size = (int)floor(sigma*6) / 2; filter_size = filter_size * 2 + 1; // If 3 sigma is less than a pixel, why bother (ie sigma < 2/3) if(filter_size < 3) return; // Filter, or downsample and recurse if (filter_size < 10) { #ifdef USE_EXACT_SIGMA FilterGaussian(img, sigma) #else cvSmooth( img, img, CV_GAUSSIAN, filter_size, filter_size ); #endif } else { if (img->width < 2 || img->height < 2) return; IplImage* sub_img = cvCreateImage(cvSize(img->width / 2, img->height / 2), img->depth, img->nChannels); cvPyrDown( img, sub_img ); FastFilter( sub_img, sigma / 2.0 ); cvResize( sub_img, img, CV_INTER_LINEAR ); cvReleaseImage( &sub_img ); } } // // Retinex // // Summary: // Basic retinex restoration. The image and a filtered image are converted // to the log domain and subtracted. // // Arguments: // img - an IplImage to be enhanced in place. // sigma - the standard deviation of the gaussian kernal used to filter. // gain - the factor by which to scale the image back into visable range. // offset - an offset similar to the gain. // void Retinex(IplImage *img, double sigma, int gain, int offset) { IplImage *A, *fA, *fB, *fC; // Initialize temp images fA = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fB = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fC = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); // Compute log image cvConvert( img, fA ); cvLog( fA, fB ); // Compute log of blured image A = cvCloneImage( img ); FastFilter( A, sigma ); cvConvert( A, fA ); cvLog( fA, fC ); // Compute difference cvSub( fB, fC, fA ); // Restore cvConvertScale( fA, img, gain, offset); // Release temp images cvReleaseImage( &A ); cvReleaseImage( &fA ); cvReleaseImage( &fB ); cvReleaseImage( &fC ); } // // MultiScaleRetinex // // Summary: // Multiscale retinex restoration. The image and a set of filtered images are // converted to the log domain and subtracted from the original with some set // of weights. Typicaly called with three equaly weighted scales of fine, // medium and wide standard deviations. // // Arguments: // img - an IplImage to be enhanced in place. // sigma - the standard deviation of the gaussian kernal used to filter. // gain - the factor by which to scale the image back into visable range. // offset - an offset similar to the gain. // void MultiScaleRetinex(IplImage *img, int scales, double *weights, double *sigmas, int gain, int offset) { int i; double weight; IplImage *A, *fA, *fB, *fC; // Initialize temp images fA = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fB = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fC = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); // Compute log image cvConvert( img, fA ); cvLog( fA, fB ); // Normalize according to given weights for (i = 0, weight = 0; i < scales; i++) weight += weights[i]; if (weight != 1.0) cvScale( fB, fB, weight ); // Filter at each scale for (i = 0; i < scales; i++) { A = cvCloneImage( img ); FastFilter( A, sigmas[i] ); cvConvert( A, fA ); cvLog( fA, fC ); cvReleaseImage( &A ); // Compute weighted difference cvScale( fC, fC, weights[i] ); cvSub( fB, fC, fB ); } // Restore cvConvertScale( fB, img, gain, offset); // Release temp images cvReleaseImage( &fA ); cvReleaseImage( &fB ); cvReleaseImage( &fC ); } // // MultiScaleRetinexCR // // Summary: // Multiscale retinex restoration with color restoration. The image and a set of // filtered images are converted to the log domain and subtracted from the // original with some set of weights. Typicaly called with three equaly weighted // scales of fine, medium and wide standard deviations. A color restoration weight // is then applied to each color channel. // // Arguments: // img - an IplImage to be enhanced in place. // sigma - the standard deviation of the gaussian kernal used to filter. // gain - the factor by which to scale the image back into visable range. // offset - an offset similar to the gain. // restoration_factor - controls the non-linearaty of the color restoration. // color_gain - controls the color restoration gain. // void MultiScaleRetinexCR(IplImage *img, int scales, double *weights, double *sigmas, int gain, int offset, double restoration_factor, double color_gain) { int i; double weight; IplImage *A, *B, *C, *fA, *fB, *fC, *fsA, *fsB, *fsC, *fsD, *fsE, *fsF; // Initialize temp images fA = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fB = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fC = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, img->nChannels); fsA = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); fsB = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); fsC = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); fsD = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); fsE = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); fsF = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_32F, 1); // Compute log image cvConvert( img, fB ); cvLog( fB, fA ); // Normalize according to given weights for (i = 0, weight = 0; i < scales; i++) weight += weights[i]; if (weight != 1.0) cvScale( fA, fA, weight ); // Filter at each scale for (i = 0; i < scales; i++) { A = cvCloneImage( img ); FastFilter( A, sigmas[i] ); cvConvert( A, fB ); cvLog( fB, fC ); cvReleaseImage( &A ); // Compute weighted difference cvScale( fC, fC, weights[i] ); cvSub( fA, fC, fA ); } // Color restoration if (img->nChannels > 1) { A = cvCreateImage(cvSize(img->width, img->height), img->depth, 1); B = cvCreateImage(cvSize(img->width, img->height), img->depth, 1); C = cvCreateImage(cvSize(img->width, img->height), img->depth, 1); // Divide image into channels, convert and store sum cvCvtPixToPlane( img, A, B, C, NULL ); cvConvert( A, fsA ); cvConvert( B, fsB ); cvConvert( C, fsC ); cvReleaseImage( &A ); cvReleaseImage( &B ); cvReleaseImage( &C ); // Sum components cvAdd( fsA, fsB, fsD ); cvAdd( fsD, fsC, fsD ); // Normalize weights cvDiv( fsA, fsD, fsA, restoration_factor); cvDiv( fsB, fsD, fsB, restoration_factor); cvDiv( fsC, fsD, fsC, restoration_factor); cvConvertScale( fsA, fsA, 1, 1 ); cvConvertScale( fsB, fsB, 1, 1 ); cvConvertScale( fsC, fsC, 1, 1 ); // Log weights cvLog( fsA, fsA ); cvLog( fsB, fsB ); cvLog( fsC, fsC ); // Divide retinex image, weight accordingly and recombine cvCvtPixToPlane( fA, fsD, fsE, fsF, NULL ); cvMul( fsD, fsA, fsD, color_gain); cvMul( fsE, fsB, fsE, color_gain ); cvMul( fsF, fsC, fsF, color_gain ); cvCvtPlaneToPix( fsD, fsE, fsF, NULL, fA ); } // Restore cvConvertScale( fA, img, gain, offset); // Release temp images cvReleaseImage( &fA ); cvReleaseImage( &fB ); cvReleaseImage( &fC ); cvReleaseImage( &fsA ); cvReleaseImage( &fsB ); cvReleaseImage( &fsC ); cvReleaseImage( &fsD ); cvReleaseImage( &fsE ); cvReleaseImage( &fsF ); }
这种混合算法代码:
我参考一个matlab代码写的
c版
// author : [email protected] // data : 4/20/2011 /* %%%%%%%%%%%%%%%RGB normalization%%%%%%%%%%%%%%%%%%%%%% %its cascaded implementation of 1 section of paper "A FAST SKIN REGION DETECTOR" by %Phil Chen, Dr.Christos Greecos %and %section 2.1 of paper "Simple and accurate face detection in color images" by %YUI TING PAI et al % Coding by Madhava.S.Bhat, Dept of Electronics an communication %Dr.Ambedkar Institute of Technology, Bangalore %[email protected] */ #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <iostream> #include <algorithm> using namespace std; void cvCompensationGlobal1(IplImage* _src,IplImage* dst) { static const int B=0; static const int G=1; static const int R=2; int width=_src->width; int height=_src->height; //double IplImage* src=cvCreateImage(cvGetSize(_src),IPL_DEPTH_64F,3); CvScalar minV=cvScalar(255,255,255,0); for (int h=0;h<height;h++) { unsigned char* p=(unsigned char*)_src->imageData+h*_src->widthStep; double* pc=(double*)(src->imageData+h*src->widthStep); for (int w=0;w<width;w++) { for (int i=0;i<3;i++) { *pc=*p; if (minV.val[i]>*pc) { minV.val[i]=*pc; } pc++; p++; } } } cvSubS(src,minV,src); int blackNum=0; double total=0; double acc[3]={0}; for (int h=0;h<height;h++) { double* p=(double*)(src->imageData+h*src->widthStep); for (int w=0;w<width;w++) { if (p[0]<0.001&&p[1]<0.001&&p[2]<0.001) { blackNum++; p+=3; continue; } double a=p[R]; double b=p[R]; if (p[B]<a) { a=p[B]; }else { b=p[B]; } if (p[G]<a) { a=p[G]; }else { b=p[G]; } total+=a+b; for (int i=0;i<3;i++) { acc[i]+=p[i]; } p+=3; } } double avgT=total/(2*(width*height-blackNum)); CvScalar avg; IplImage* rgb[3]; for (int i=0;i<3;i++) { rgb[i]=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); avg.val[i]=(double)acc[i]/(width*height); avg.val[i]=avgT/avg.val[i]; } cvSplit(src,rgb[0],rgb[1],rgb[2],0); for (int i=0;i<3;i++) { cvScale(rgb[i],rgb[i],avg.val[i]);//bigger than 255 } cvMerge(rgb[0],rgb[1],rgb[2],0,src); //y component only IplImage* y=cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); for (int h=0;h<height;h++) { double* psrc=(double*)(src->imageData+h*src->widthStep); double* py=(double*)(y->imageData+h*y->widthStep); for (int w=0;w<width;w++) { *py++=psrc[R]*0.299+psrc[G]*0.587+psrc[B]*0.114; psrc+=3; } } double maxY=0; double minY=0; cvMinMaxLoc(y,&minY,&maxY); double sumY=0; //scale for (int h=0;h<height;h++) { double* p=(double*)(y->imageData+h*y->widthStep); for (int w=0;w<width;w++) { *p=(*p-minY)/(maxY-minY); sumY+=*p; p++; } } sumY*=255; sumY/=width*height; double scale=1.; if (sumY<64) { scale=1.4; }else if (sumY>192) { scale=0.6; } if (abs(scale-1.)>0.001) { for (int h=0;h<height;h++) { double* psrc=(double*)(src->imageData+h*src->widthStep); unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep; double t[3]; for (int w=0;w<width;w++) { t[0]=pow(psrc[R],scale); t[1]=pow(psrc[G],scale); t[2]=psrc[B]; for (int i=0;i<3;i++) { if (t[i]>255) { pdst[i]=255; }else { pdst[i]=(unsigned char)t[i]; } } psrc+=3; pdst+=3; } } }else{ for (int h=0;h<height;h++) { double* psrc=(double*)(src->imageData+h*src->widthStep); unsigned char* pdst=(unsigned char*)dst->imageData+h*dst->widthStep; for (int w=0;w<width;w++) { for (int i=0;i<3;i++) { double t=*psrc++; if (t>255) { *pdst++=255; }else { *pdst++=(unsigned char)t; } } } } } //free memory cvReleaseImage(&src); cvReleaseImage(&y); for (int i=0;i<3;i++) { cvReleaseImage(&rgb[i]); } }
matlab 版,算法没问题,但代码写的不太好,我做了点修改
%%%%%%%%%%%%%%%RGB normalisation%%%%%%%%%%%%%%%%%%%%%% %its cascaded implementain of 1 section of paper "A FAST SKIN REGION DETECTOR" by %Phil Chen, Dr.Christos Greecos %and %section 2.1 of paper "Simple and accurate face detection in color images" by %YUI TING PAI et al % Coding by Madhava.S.Bhat, Dept of Electronics an communication %Dr.Ambedkar Institute of Technology, Bangalore %[email protected] function[]= imag_improve_rgb(IMG) figure,imshow(IMG) title('original') R=double(IMG(:,:,1)); G=double(IMG(:,:,2)); B=double(IMG(:,:,3)); [H,W]=size(R); % minR=0; % minG=0; % minB=0; % [srow,scol]=find(R==0 & G==0 & B==0); % if(isempty(srow) && isempty(scol)) minR=min(min(R)) minG=min(min(G)) minB=min(min(B)) % end R=R-minR; G=G-minG; B=B-minB; S=zeros(H,W); [srow,scol]=find(R==0 & G==0 & B==0); [sm,sn]=size(srow); for i=1:sm S(srow(i),scol(i))=1; end mstd=sum(sum(S)) Nstd=(H*W)-mstd; Cst=0; Cst=double(Cst); for i=1:H for j=1:W a=R(i,j); b=R(i,j); if(B(i,j)<a) a=B(i,j); else b=B(i,j); end if(G(i,j)<a) a=G(i,j); else b=G(i,j); end Cst=a+b+Cst; end end %%%%sum of black pixels%%%%%%%%%%% blacksumR=0; blacksumG=0; blacksumB=0; for i=1:sm blacksumR=blacksumR+R(srow(i),scol(i)); blacksumG=blacksumG+G(srow(i),scol(i)); blacksumB=blacksumB+B(srow(i),scol(i)); end Cstd = Cst/(2*Nstd) CavgR=sum(sum(R))./(H*W) CavgB=sum(sum(B))./(H*W) CavgG=sum(sum(G))./(H*W) Rsc=Cstd./CavgR Gsc=Cstd./CavgG Bsc=Cstd/CavgB R=R.*Rsc; G=G.*Gsc; B=B.*Bsc; C(:,:,1)=R; C(:,:,2)=G; C(:,:,3)=B; C=C/255; YCbCr=rgb2ycbcr(C); Y=YCbCr(:,:,1); figure,imshow(C) title('aft 1st stage of compensation') %normalize Y minY=min(min(Y)); maxY=max(max(Y)); Y=255.0*(Y-minY)./(maxY-minY); YEye=Y; Yavg=sum(sum(Y))/(W*H) T=1; if (Yavg<64) T=1.4 elseif (Yavg>192) T=0.6 end T if (T~=1) RI=R.^T; GI=G.^T; else RI=R; GI=G; end Cfinal(:,:,1)=uint8(RI); Cfinal(:,:,2)=uint8(GI); Cfinal(:,:,3)=uint8(B); figure,imshow(Cfinal) title('Light intensity compensated') % YCbCr=rgb2ycbcr(Cnew);