多尺度视网膜增强算法(MSRCR)

2024-01-10 18:38

本文主要是介绍多尺度视网膜增强算法(MSRCR),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MSRCR(multi-scale retinex with color restoration)

头文件

/** Copyright (c) 2006, Douglas Gray (dgray@soe.ucsc.edu, dr.de3ug@gmail.com)* 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 (dgray@soe.ucsc.edu, dr.de3ug@gmail.com)* 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<cv.h>
#include <opencv2/opencv.hpp>
#include<omp.h>
#include <math.h>using namespace cv;
using namespace std;
//#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 10inline 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 demandsif ( 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 spacefilter = new double[filter_size];// Calculate exponentialsum = 0;for (i = 0; i < filter_size; i++) {x = i - (filter_size / 2);filter[i] = exp( -(x*x) / (2*sigma*sigma) );sum += filter[i];}// Normalizefor (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 demandsif ( 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 spacekernel = 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 demandsif ( 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 axisfor (j = 0; j < temp->height; j++)for (i = 0; i < temp->width; i++) {// inner loop has been unrolledv1 = 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 onpc(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 axisfor (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 onpc(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 demandsif ( 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 recurseif (filter_size < 10) {#ifdef USE_EXACT_SIGMAFilterGaussian(img, sigma)
#elsecvSmooth( 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 imagesfA = 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 imagecvConvert( img, fA );cvLog( fA, fB );// Compute log of blured imageA = cvCloneImage( img );FastFilter( A, sigma );cvConvert( A, fA );cvLog( fA, fC );// Compute differencecvSub( fB, fC, fA );// RestorecvConvertScale( fA, img, gain, offset);// Release temp imagescvReleaseImage( &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 imagesfA = 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 imagecvConvert( img, fA );cvLog( fA, fB );// Normalize according to given weightsfor (i = 0, weight = 0; i < scales; i++)weight += weights[i];if (weight != 1.0) cvScale( fB, fB, weight );// Filter at each scalefor (i = 0; i < scales; i++) {A = cvCloneImage( img );FastFilter( A, sigmas[i] );cvConvert( A, fA );cvLog( fA, fC );cvReleaseImage( &A );// Compute weighted differencecvScale( fC, fC, weights[i] );cvSub( fB, fC, fB );}// RestorecvConvertScale( fB, img, gain, offset);// Release temp imagescvReleaseImage( &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.
////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);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 imagesfA = 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 imagecvConvert( img, fB );cvLog( fB, fA );=================get image value===================//   const int height=26;//const int width=30;//float imageValue[height][width][3];//for(int i=0;i<img->height;i++)	//{//	for(int j=0;j<img->width;j++)//	{//		imageValue[i][j][0]=cvGet2D(fA,i,j).val[0];//		imageValue[i][j][1]=cvGet2D(fA,i,j).val[1];//		imageValue[i][j][2]=cvGet2D(fA,i,j).val[2];//	}//}===========================end======================//=============================show image================//IplImage * test = cvCreateImage(cvSize(img->width, img->height), IPL_DEPTH_8U, img->nChannels);//cvConvert(fB,test);//cvNamedWindow("test",CV_WINDOW_AUTOSIZE);//cvShowImage("test",test);//cvWaitKey(0);==========================end============================// Normalize according to given weightsfor (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 differencecvScale( fC, fC, weights[i] );cvSub( fA, fC, fA );}// Color restorationif (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 sumcvCvtPixToPlane( img, A, B, C, NULL );cvConvert( A, fsA );cvConvert( B, fsB );cvConvert( C, fsC );cvReleaseImage( &A );cvReleaseImage( &B );cvReleaseImage( &C );// Sum componentscvAdd( fsA, fsB, fsD );cvAdd( fsD, fsC, fsD );// Normalize weightscvDiv( 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 weightscvLog( fsA, fsA );cvLog( fsB, fsB );cvLog( fsC, fsC );// Divide retinex image, weight accordingly and recombinecvCvtPixToPlane( 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 );}// RestorecvConvertScale( fA, img, gain, offset);// Release temp imagescvReleaseImage( &fA );cvReleaseImage( &fB );cvReleaseImage( &fC );cvReleaseImage( &fsA );cvReleaseImage( &fsB );cvReleaseImage( &fsC );cvReleaseImage( &fsD );cvReleaseImage( &fsE );cvReleaseImage( &fsF );
}


主函数文件

//#include "stdafx.h"
#include<tchar.h>
#include <opencv2/opencv.hpp>
#include<iostream>
#include<sstream>
#include<string>
#include<cv.h>
#include<omp.h>
#include<concrt.h>#include"retinex.h"using namespace std;
using namespace cv;//============================================using for handle single image==================================================
int _tmain(int argc, _TCHAR* argv[])
{//get image const char* imagename = "girl.jpg";const char* imagesavename="girl_retinex.jpg";/*const char* imagename[6] = {"example12.jpg","girl01.jpg","people01.jpg","road01.jpg","tree01.jpg","clock.bmp"};const char* imagesavename[6] = {"example12_retinex.jpg","girl01_retinex.jpg","people01_retinex.jpg","road01_retinex.jpg","tree01_retinex.jpg","clock_retinex.bmp"};*///set retinex parametersint scales=3;double weight[3]={1.0/3.0,1.0/3.0,1.0/3.0};double sigmas[3]={1,50,100};                   //- the standard deviation of the gaussian kernal used to filter.int gain=50;                                   //- the factor by which to scale the image back into visable range.int offset=150;                                 //- an offset similar to the gain.double restoration_factor=100;                    // - controls the non-linearaty of the color restoration.double color_gain=1;                            // - controls the color restoration gain.char filePath[200]="image\\";char* imagePath=filePath;//get savefilenamechar num[5];char* sigmas_char[3];stringstream ss;for(int j=0;j<3;j++){						sigmas_char[j]=num;ss<<sigmas[j];ss>>sigmas_char[j];imagePath=strcat(imagePath,"sigma=");imagePath=strcat(imagePath,sigmas_char[j]);ss.clear();ss.str("");}//gainss.clear();ss.str("");char* gain_c=num;ss<<gain;ss>>gain_c;imagePath=strcat(imagePath,"_gain=");imagePath=strcat(imagePath,gain_c);//offsetss.clear();ss.str("");char* offset_char=num;ss<<offset;ss>>offset_char;imagePath=strcat(imagePath,"_offset=");imagePath=strcat(imagePath,offset_char);//restoration_factorss.clear();ss.str("");char* restoration_factor_char=num;ss<<restoration_factor;ss>>restoration_factor_char;imagePath=strcat(imagePath,"_factor=");imagePath=strcat(imagePath,restoration_factor_char);//color_gainss.clear();ss.str("");char* color_gain_char=num;ss<<color_gain;ss>>color_gain_char;imagePath=strcat(imagePath,"_color_gain=");imagePath=strcat(imagePath,color_gain_char);ss.clear();ss.str("");const char* imageSavePath=strcat(imagePath,imagesavename);IplImage* img=cvLoadImage(imagename,-1);//read the original channels number from imageMultiScaleRetinexCR(img,scales,weight,sigmas, gain, offset,restoration_factor,color_gain);cvSaveImage(imageSavePath,img);cvReleaseImage(&img);return 0;
}
============================================end=========================================================//==========================================using for handle video==============================
//int _tmain(int argc, _TCHAR* argv[])
//{ 
//	//get core num
//	int coreNum=omp_get_num_procs();
//
//	IplImage* pFrame=NULL;
//	CvCapture* pCapture=NULL;
//
//	cvNamedWindow("orginalVideo",1);
//	cvNamedWindow("retinexVideo",1);
//
//	cvMoveWindow("video",30,0);
//	cvMoveWindow("retinexVideo",360,0);
//
//	const char* videoName="sister.avi";
//	if(!(pCapture=cvCaptureFromFile(videoName)))
//	{
//		fprintf(stderr, "Can not open video file %s\n", videoName);
//		return -1;
//	}
//
//	/*CvVideoWriter *writer=0;
//	int isColor=1;
//	int fps=cvGetCaptureProperty(pCapture,CV_CAP_PROP_FPS);
//	int frameW=cvGetCaptureProperty(pCapture,CV_CAP_PROP_FRAME_HEIGHT);
//	int frameH=cvGetCaptureProperty(pCapture,CV_CAP_PROP_FRAME_WIDTH);
//	int numFrames = (int) cvGetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_COUNT); 
//	writer=cvCreateVideoWriter("sister2retinex.avi",CV_FOURCC('M','J','P','G'),
//                           fps,cvSize(frameH,frameW),isColor);*/
//
//	//set paramaters
//	int scales=3;
//	double *weights,weight[3]={1.0/3.0,1.0/3.0,1.0/3.0};
//	weights=&weight[0];
//	double *sigmas, simg[3]={10,50,100};
//	sigmas=&simg[0];
//	
//	int count=0;
//
//	while((pFrame=cvQueryFrame(pCapture))!=NULL)
//	{
//		count++;
//		cvShowImage("orginalVideo",pFrame);
//		cvWaitKey(1);
//		MultiScaleRetinexCR(pFrame,scales,weights,sigmas, 128, 128,6,2);
//		/*cvWriteFrame(writer,pFrame);*/
//		cvShowImage("retinexVideo",pFrame);
//		//cout<<count<<"/"<<numFrames<<endl;
//	}
//	cvDestroyWindow("orginalVideo");
//	cvDestroyWindow("retinexVideo");
//
//	cvReleaseImage(&pFrame);
//	cvReleaseCapture(&pCapture);
//	//cvReleaseVideoWriter(&writer);
//	return 0;
//}
//=====================================end========================================================


====================================================================================

改进版 视网膜增强算法

====================================================================================

问题:

上面给出的源码,实现后,在颜色比较鲜艳时,或者颜色为黑色时,会产生变色(比如黑色会变为红色,红色会变为黄色)

产生原因:

RGB值比较大的值(接近255) 或比较低的(接近0 ) 经过上述算法处理后,某一通道的值会超过255或低于0,溢出。


改进:

改进版本可参考reference 3(网站包含论文与demo ,源码(Linux版本))



Reference:

1.原理相关1:http://www.cnblogs.com/Imageshop/archive/2013/04/17/3026881.html

2.源码部分2:http://blog.csdn.net/onezeros/article/details/6342661

---------------------------------------------------------------------------------------------------------------

3.改进版本:http://www.ipol.im/pub/art/2014/107/

















这篇关于多尺度视网膜增强算法(MSRCR)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591708

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯: