简介
本篇是对实现图片处理功能:【调整】实现的记录。
亮度调整
实现原理
利用公式:g(i,j) = contrast*f(i,j)+brightness。在原图像基础上,根据拖动条的数据大小,整体的加上或者减去不同的brightness。 实现图像的亮度调整。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightness
(JNIEnv* env, jclass obj, jlong imageBrightness, jint value){
double beta = 0.0, alpha = 1.0;
value = value - 50;
beta = value * 2;
Mat mat = Mat(*((Mat*)imageBrightness));
mat.convertTo(mat, -1, alpha, beta);
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightness
(JNIEnv* env, jclass obj, jlong imageBrightness, jint value){
double beta = 0.0, alpha = 1.0;
value = value - 50;
beta = value * 2;
Mat mat = Mat(*((Mat*)imageBrightness));
mat.convertTo(mat, -1, alpha, beta);
}
函数传入的参数value就是对应拖动条的数据,范围在0到100之间,beta为需要被加上的亮度数据。
当大于50的时候,beta范围为0 - 100,对应图片mat亮度增加。 当小于50的时候,deta范围为0 - (-100),对应图片亮度降低。
效果演示
对应的效果图片如下:
亮度降低 亮度增加
AWB调整
实现原理
简单的说就是,图像R和B通道数据的增减,来实现图像整体偏冷或者偏暖。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicAWB
(JNIEnv* env, jclass obj, jlong imageAWB, jint value){
int width, height, k, j;
IplImage src1;
CvScalar s1;
Mat mat = Mat(*((Mat*)imageAWB));
src1 = mat;
width = mat.rows;
height = mat.cols;
if(value > 50){
value = (value - 50) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(&src1, k, j);
s1.val[0] = s1.val[0] + value;
cvSet2D(&src1, k, j, s1);
}
}
}else{
value = (50 - value) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(&src1, k, j);
s1.val[2] = s1.val[2] + value;
cvSet2D(&src1, k, j, s1);
}
}
}
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicAWB
(JNIEnv* env, jclass obj, jlong imageAWB, jint value){
int width, height, k, j;
IplImage src1;
CvScalar s1;
Mat mat = Mat(*((Mat*)imageAWB));
src1 = mat;
width = mat.rows;
height = mat.cols;
if(value > 50){
value = (value - 50) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(&src1, k, j);
s1.val[0] = s1.val[0] + value;
cvSet2D(&src1, k, j, s1);
}
}
}else{
value = (50 - value) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(&src1, k, j);
s1.val[2] = s1.val[2] + value;
cvSet2D(&src1, k, j, s1);
}
}
}
}
同样的函数传入的参数value就是拖动条数据,拖动条默认数据为50。当大于50的时候,增加图像R通道的数据,让图像偏暖;当小于50的时候,
增加图像B通道的数据,让图像偏冷。
效果演示
对应的效果图片如下:
偏冷效果 偏暖效果
对比度调整
实现原理
同样利用公式:g(i,j) = contrast*f(i,j)+brightness。在原图像基础上,根据拖动条的数据大小,整体的乘上contrast,根据contrast的不同,来实现图像的亮度调整。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicContrast
(JNIEnv* env, jclass obj, jlong imageContrast, jint value){
double alpha = 1.0;
if(value > 50){
value = value - 50;
alpha = alpha + ((double)value / 25);
}else{
alpha = alpha - ((double)(50 - value) / 50);
}
Mat mat = Mat(*((Mat*)imageContrast));
mat.convertTo(mat, -1, alpha, 0);
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicContrast
(JNIEnv* env, jclass obj, jlong imageContrast, jint value){
double alpha = 1.0;
if(value > 50){
value = value - 50;
alpha = alpha + ((double)value / 25);
}else{
alpha = alpha - ((double)(50 - value) / 50);
}
Mat mat = Mat(*((Mat*)imageContrast));
mat.convertTo(mat, -1, alpha, 0);
}
同样的,拖动条数据value默认为50,当value大于50的时候,alpha也就是contrast大于1,对比机增加;当value小于50的时候,alpha小于1,对比多降低。
效果演示
对应的效果图片如下:
对比度增加 对比度降低
饱和度调整
实现原理
将rgb图像,转换为hsv格式之后,其中的s分量就表示为饱和度,通过增加、减小该分量来实现饱和度的增减。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSaturation
(JNIEnv* env, jclass obj, jlong imagePicsaturation, jint value){
int width, height, k, j;
CvScalar s1;
IplImage src;
Mat mat = Mat(*((Mat*)imagePicsaturation));
src = mat;
IplImage *hsv_img = cvCreateImage(cvGetSize(&src), 8 , 3);
width = mat.rows;
height = mat.cols;
cvCvtColor(&src, hsv_img, CV_BGR2HSV);
value = (value - 50) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(hsv_img, k, j);
s1.val[1] = s1.val[1] + value;
if(s1.val[1] < 0){
s1.val[1] = 0;
}else if(s1.val[1] > 255){
s1.val[1] = 255;
}
cvSet2D(hsv_img, k, j, s1);
}
}
cvCvtColor(hsv_img, &src, CV_HSV2BGR);
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSaturation
(JNIEnv* env, jclass obj, jlong imagePicsaturation, jint value){
int width, height, k, j;
CvScalar s1;
IplImage src;
Mat mat = Mat(*((Mat*)imagePicsaturation));
src = mat;
IplImage *hsv_img = cvCreateImage(cvGetSize(&src), 8 , 3);
width = mat.rows;
height = mat.cols;
cvCvtColor(&src, hsv_img, CV_BGR2HSV);
value = (value - 50) * 2;
for(k = 0; k < width; k++){
for(j= 0; j< height; j++){
s1 = cvGet2D(hsv_img, k, j);
s1.val[1] = s1.val[1] + value;
if(s1.val[1] < 0){
s1.val[1] = 0;
}else if(s1.val[1] > 255){
s1.val[1] = 255;
}
cvSet2D(hsv_img, k, j, s1);
}
}
cvCvtColor(hsv_img, &src, CV_HSV2BGR);
}
首先将图像转换为HSV格式,接着根据拖动条数值是大于50还是小于50,来计算是增加S通道分量还是降低S通道分量。最后将图像从新转换会BGR格式。
效果演示
对应的效果图片如下:
饱和度增加 饱和度降低
锐度调整
实现原理
通过对图像的模糊来降低图像锐度;首先将图像模糊,接着用模糊图像减去原图像,再与原图像相加,从而增加图像锐度。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSharpness
(JNIEnv* env, jclass obj, jlong imageSharpness, jint value){
int width, height, i, j;
IplImage pI_1, pI_2;
CvScalar s1, s2;
Mat mat1 = Mat(*((Mat*)imageSharpness));
width = mat1.rows;
height = mat1.cols;
Mat mat2 = cv::Mat(width, height, CV_8UC3, 1);
int sharpness_now;
pI_1 = mat1;
pI_2 = mat2;
if(value < 50){
sharpness_now = 3 + 2 *((50 - value) / 10);
cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s2.val[0];
s1.val[1] = s2.val[1];
s1.val[2] = s2.val[2];
cvSet2D(&pI_1, i, j, s1);
}
}
}else{
sharpness_now = 3 + 2 * ((value - 50) / 10);
cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s1.val[0] - s2.val[0];
s1.val[1] = s1.val[1] - s2.val[1];
s1.val[2] = s1.val[2] - s2.val[2];
cvSet2D(&pI_2, i, j, s1);
}
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s1.val[0] + s2.val[0];
s1.val[1] = s1.val[1] + s2.val[1];
s1.val[2] = s1.val[2] + s2.val[2];
cvSet2D(&pI_1, i, j, s1);
}
}
}
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicSharpness
(JNIEnv* env, jclass obj, jlong imageSharpness, jint value){
int width, height, i, j;
IplImage pI_1, pI_2;
CvScalar s1, s2;
Mat mat1 = Mat(*((Mat*)imageSharpness));
width = mat1.rows;
height = mat1.cols;
Mat mat2 = cv::Mat(width, height, CV_8UC3, 1);
int sharpness_now;
pI_1 = mat1;
pI_2 = mat2;
if(value < 50){
sharpness_now = 3 + 2 *((50 - value) / 10);
cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s2.val[0];
s1.val[1] = s2.val[1];
s1.val[2] = s2.val[2];
cvSet2D(&pI_1, i, j, s1);
}
}
}else{
sharpness_now = 3 + 2 * ((value - 50) / 10);
cvSmooth(&pI_1, &pI_2, CV_GAUSSIAN, sharpness_now, 0, 0, 0);
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s1.val[0] - s2.val[0];
s1.val[1] = s1.val[1] - s2.val[1];
s1.val[2] = s1.val[2] - s2.val[2];
cvSet2D(&pI_2, i, j, s1);
}
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&pI_1, i, j);
s2 = cvGet2D(&pI_2, i, j);
s1.val[0] = s1.val[0] + s2.val[0];
s1.val[1] = s1.val[1] + s2.val[1];
s1.val[2] = s1.val[2] + s2.val[2];
cvSet2D(&pI_1, i, j, s1);
}
}
}
}
当拖动条数据value小于50的时候,使用cvSmooth直接对图像进行模糊;当value大于50的时候,首先cvSmooth模糊图像到pI_2中,接着pI_2减去原图像、pI_1,处理后的数据,继续放入pI_2中。最后将pI_2的数据和原图像pI_1相加,达到锐化效果。
效果演示
对应的效果图片如下:
锐度降低 锐度增加
亮处细节
实现原理
首先统计出图像[0,255]的直方图数据,计算出图像像素从0开始到占据所有像素点50%时候的像素值;接着计算出到占据80%时候的对应的像素值。剩下20%的像素点,默认为亮处数据,之前统计的80%数据为非亮处像素。 将80%的非亮处像素,从新映射到0到之前50%时候像素值范围,将20%的亮处数据映射到之前统计的50%像素值到本图像最大像素值区间范围内。 相当于增大了亮处数据的对比度。从而使得亮处的细节更加清楚。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightnessDetile
(JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
int width, height, i, j;
IplImage src1;
CvScalar s1;
int hist_size = 256;
int hist_height = 256;
IplImage* Y_plane;
CvHistogram* Y_hist;
float range[] = {0,255};
float* ranges[]={range};
float high_val[2], tmp;
float scale[hist_size];
float scale_number[hist_size];
float scale_flag[2];
float throwld = 0.4 + value / 333.3;
Mat mat = Mat(*((Mat*)imageDarkdetile));
src1 = mat;
width = mat.rows;
height = mat.cols;
cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
Y_plane = cvCreateImage(cvGetSize(&src1), 8, 1);
cvSplit(&src1, Y_plane, NULL, NULL, NULL);
Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&Y_plane, Y_hist, 0, 0);
cvNormalizeHist(Y_hist, 1.0);
for(i=0; i<hist_size; i++){
high_val[0] = cvQueryHistValue_1D(Y_hist, i);
scale[i] = 0;
if(i == 0){
scale[i] = high_val[0];
}else{
scale[i] = scale[i - 1] + high_val[0];
}
if(scale[i] < throwld){
scale_flag[0] = i;
}else if(scale[i] > 0.8){
scale_flag[1] = i;
high_val[0] = scale_flag[0] / scale_flag[1];
high_val[1] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
break;
}
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&src1, i, j);
if(s1.val[0] < scale_flag[1]){
s1.val[0] = s1.val[0] * high_val[0];
}else{
s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[1];
if(s1.val[0] > 255){
s1.val[0] = 255;
}
}
cvSet2D(&src1, i, j, s1);
}
}
cvCvtColor(&src1, &src1, CV_YCrCb2BGR);
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicBrightnessDetile
(JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
int width, height, i, j;
IplImage src1;
CvScalar s1;
int hist_size = 256;
int hist_height = 256;
IplImage* Y_plane;
CvHistogram* Y_hist;
float range[] = {0,255};
float* ranges[]={range};
float high_val[2], tmp;
float scale[hist_size];
float scale_number[hist_size];
float scale_flag[2];
float throwld = 0.4 + value / 333.3;
Mat mat = Mat(*((Mat*)imageDarkdetile));
src1 = mat;
width = mat.rows;
height = mat.cols;
cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
Y_plane = cvCreateImage(cvGetSize(&src1), 8, 1);
cvSplit(&src1, Y_plane, NULL, NULL, NULL);
Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&Y_plane, Y_hist, 0, 0);
cvNormalizeHist(Y_hist, 1.0);
for(i=0; i<hist_size; i++){
high_val[0] = cvQueryHistValue_1D(Y_hist, i);
scale[i] = 0;
if(i == 0){
scale[i] = high_val[0];
}else{
scale[i] = scale[i - 1] + high_val[0];
}
if(scale[i] < throwld){
scale_flag[0] = i;
}else if(scale[i] > 0.8){
scale_flag[1] = i;
high_val[0] = scale_flag[0] / scale_flag[1];
high_val[1] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
break;
}
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&src1, i, j);
if(s1.val[0] < scale_flag[1]){
s1.val[0] = s1.val[0] * high_val[0];
}else{
s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[1];
if(s1.val[0] > 255){
s1.val[0] = 255;
}
}
cvSet2D(&src1, i, j, s1);
}
}
cvCvtColor(&src1, &src1, CV_YCrCb2BGR);
将图像转化为YCrCb格式,接着分离出Y通道,对y通道数据统计直方图,throwld 对应为之前说的50%阀值,该阀值根据拖动条变化,阀值越低,亮处
细节效果越明显,将阀值throwld和80%处的像素值大小,保存到scale_flag数组中。接着计算出从新映射的公式。 最后通过: s1.val[0] = s1.val[0] * high_val[0]; s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[1]; 对图像亮处像素和非亮处像素进行重新映射,然后将图像格式从新转换回BGR格式。
效果演示
对应的效果图片如下:
原图像 亮处细节
暗处细节
实现原理
和之前的亮度细节类似,区别是亮处细节时候,是从0开始统计到50%为阀值,80%以上为亮处细节。这里是从255开始。像素值递减的统计,也是50%为阀值。 80%以上的数据的暗处细节。最后将非暗处细节的数据,从新映射到255开始统计的,50%像素范围内,将暗处细节数据映射到50%像素开始到像素 值为0的像素范围内。
具体代码
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicDarkDetile
(JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
int width, height, i, j = 0;
IplImage src1;
CvScalar s1;
int hist_size = 256;
int hist_height = 256;
IplImage* Y_plane;
CvHistogram* Y_hist;
float range[] = {0,255};
float* ranges[]={range};
float high_val[2], tmp;
float scale[hist_size];
float scale_number[hist_size];
float scale_flag[2];
float throwld = 0.4 + value / 333.3;
Mat mat = Mat(*((Mat*)imageDarkdetile));
src1 = mat;
width = mat.rows;
height = mat.cols;
cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
Y_plane = cvCreateImage(cvGetSize(&src1), 8, 1);
cvSplit(&src1, Y_plane, NULL, NULL, NULL);
Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&Y_plane, Y_hist, 0, 0);
cvNormalizeHist(Y_hist, 1.0);
for(i=hist_size - 1; i>0; i--){
high_val[0] = cvQueryHistValue_1D(Y_hist, i);
scale[j] = 0;
if(j == 0){
scale[j] = high_val[0];
}else{
scale[j] = scale[j - 1] + high_val[0];
}
if(scale[j] < throwld){
scale_flag[0] = i;
}else if(scale[j] > 0.8){
scale_flag[1] = i;
high_val[0] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
high_val[1] = scale_flag[0] / scale_flag[1];
break;
}
j++;
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&src1, i, j);
if(s1.val[0] > scale_flag[1]){
s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[0];
}else{
s1.val[0] = s1.val[0] * high_val[1];
}
cvSet2D(&src1, i, j, s1);
}
}
cvCvtColor(&src1, &src1, CV_YCrCb2BGR);
}
JNIEXPORT void JNICALL Java_com_example_myadjust_MyPicAdjust_changePicDarkDetile
(JNIEnv* env, jclass obj, jlong imageDarkdetile, jint value){
int width, height, i, j = 0;
IplImage src1;
CvScalar s1;
int hist_size = 256;
int hist_height = 256;
IplImage* Y_plane;
CvHistogram* Y_hist;
float range[] = {0,255};
float* ranges[]={range};
float high_val[2], tmp;
float scale[hist_size];
float scale_number[hist_size];
float scale_flag[2];
float throwld = 0.4 + value / 333.3;
Mat mat = Mat(*((Mat*)imageDarkdetile));
src1 = mat;
width = mat.rows;
height = mat.cols;
cvCvtColor(&src1, &src1, CV_BGR2YCrCb);
Y_plane = cvCreateImage(cvGetSize(&src1), 8, 1);
cvSplit(&src1, Y_plane, NULL, NULL, NULL);
Y_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&Y_plane, Y_hist, 0, 0);
cvNormalizeHist(Y_hist, 1.0);
for(i=hist_size - 1; i>0; i--){
high_val[0] = cvQueryHistValue_1D(Y_hist, i);
scale[j] = 0;
if(j == 0){
scale[j] = high_val[0];
}else{
scale[j] = scale[j - 1] + high_val[0];
}
if(scale[j] < throwld){
scale_flag[0] = i;
}else if(scale[j] > 0.8){
scale_flag[1] = i;
high_val[0] = (255.0 - scale_flag[0]) / (255.0 - scale_flag[1]);
high_val[1] = scale_flag[0] / scale_flag[1];
break;
}
j++;
}
for(i=0; i<width; i++){
for(j=0; j<height; j++){
s1 = cvGet2D(&src1, i, j);
if(s1.val[0] > scale_flag[1]){
s1.val[0] = scale_flag[0] + (s1.val[0] - scale_flag[1]) * high_val[0];
}else{
s1.val[0] = s1.val[0] * high_val[1];
}
cvSet2D(&src1, i, j, s1);
}
}
cvCvtColor(&src1, &src1, CV_YCrCb2BGR);
}
效果演示
对应的效果图片如下:
原图像 暗处细节
具体演示下载:http://download.csdn.net/detail/u011630458/9261617