Opencv 学习---8种常用图像增强算法

常见的8种图像增强算法及其opencv实现

1.直方图均衡化

       直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。 
  这种方法通常用来增加许多图像的局部对比度。这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作。

       参考来源 openCV直方图均衡化https://blog.csdn.net/zhangfuliang123/article/details/74170894

      首先openCV没有直方图直接显示的函数,所以我们需要创建直方图来自定义绘图,函数如下:

/*
     width:直方图宽度     height:直方图高度     scale:
*/
IplImage* showImageHistogram(IplImage** image, int width, int height ,int scale){
 
    int dims = 1;
    int histSize = 256;
    float frange[] = { 0, 255 };
    float* ranges[] = { frange };
    //创建一个直方图     CV_HIST_ARRAY多维密集数组
    CvHistogram*  hist = cvCreateHist(dims, &histSize, CV_HIST_ARRAY, ranges);
    //根据输入图像计算直方图
    cvCalcHist(image, hist);
 
 
    //绘制直方图区域
    IplImage* histImage = cvCreateImage(cvSize(width*scale, height), IPL_DEPTH_8U, 1);
    //直方图背景区域置位白色
    cvRectangle(histImage, cvPoint(0, 0), cvPoint(histImage->width, histImage->height), CV_RGB(255,255,255), CV_FILLED);
    //获取最大值
    float maxHistValue = 0;
    cvGetMinMaxHistValue(hist, NULL, &maxHistValue, NULL,NULL);
    //绘制各个灰度级的直方图
    for (int i = 0; i < width; i++){
        float value = cvQueryHistValue_1D(hist, i);
        int drawHeight = cvRound((value / maxHistValue) * height);
        cvRectangle(histImage, cvPoint(i*scale, height-1), cvPoint((i+1)*scale -1, height-drawHeight), cvScalar(i, 0, 0, 0), CV_FILLED);
    }
    return histImage;
 
}


直接处理灰度图:

void histGrayChange(){
    const char* picName = "test.tif";//test.tif lenaRGB.tif
    //采用IplImage *img = cvLoadImage(picName)默认值是CV_LOAD_IMAGE_COLOR  读取无论原始图像的通道数是多少,都将被转换为3个通道读入。
    //IplImage *img = cvLoadImage(picName);
 
    //******以灰度图像读入,强制转换为单通道*****
    IplImage *img = cvLoadImage(picName,CV_LOAD_IMAGE_GRAYSCALE);
    if (img == NULL){
        cout << "Load File Failed." << endl;
    }
    cout << "ChannelL:" << img->nChannels;
 
 
    IplImage* imgDst = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    //直方图均衡化
    cvEqualizeHist(img, imgDst);
    
    cvNamedWindow("Origin", CV_WINDOW_AUTOSIZE);
    cvShowImage("Origin", img);
 
    cvNamedWindow("Result", CV_WINDOW_AUTOSIZE);
    cvShowImage("Result", imgDst);
 
    //
    int histImageWidth = 255;
    int histImageHeight = 150;
    int histImageScale = 2;
    IplImage *histImage1 = showImageHistogram(&img, histImageWidth, histImageHeight, histImageScale);
    cvNamedWindow("Hist1", CV_WINDOW_AUTOSIZE);
    cvShowImage("Hist1", histImage1);
 
    IplImage *histImage2 = showImageHistogram(&imgDst, histImageWidth, histImageHeight, histImageScale);
    cvNamedWindow("Hist2", CV_WINDOW_AUTOSIZE);
    cvShowImage("Hist2", histImage2);
 
 
    cvWaitKey();
 
    cvDestroyWindow("Origin"); cvReleaseImage(&img);
    cvDestroyWindow("Result"); cvReleaseImage(&imgDst);
 
}
 

也可以实现对彩色图片的直方图均衡化,代码就在前面的链接里,不贴了。


 

2、对数图像增强算法

      对数图像增强是图像增强的一种常见方法,其公式为: S = c log(r+1),其中c是常数(以下算法c=255/(log(256)),这样可以实现整个画面的亮度增大。

void LogEnhance(IplImage* img, IplImage* dst)
{
    // 由于oldPixel:[1,256],则可以先保存一个查找表
    uchar lut[256] ={0};
 
    double temp = 255/log(256);
 
    for ( int i =0; i<255; i++)
    {
        lut[i] = (uchar)(temp* log(i+1)+0.5);
    }
 
    for( int row =0; row <img->height; row++)
    {
        uchar *data = (uchar*)img->imageData+ row* img->widthStep;
        uchar *dstData = (uchar*)dst->imageData+ row* dst->widthStep;
 
        for ( int col = 0; col<img->width; col++)
        {
            for( int k=0; k<img->nChannels; k++)
            {
                uchar t1 = data[col*img->nChannels+k];                
                dstData[col*img->nChannels+k] = lut[t1];
            }
        }        
    }    
}

3、指数图像增强算法

 

      指数图像增强的表达为:S = cR^r,通过合理的选择c和r可以压缩灰度范围,算法以c=1.0/255.0, r=2实现。

void ExpEnhance(IplImage* img, IplImage* dst)
{
    // 由于oldPixel:[1,256],则可以先保存一个查找表
    uchar lut[256] ={0};
 
    double temp = 1.0/255.0;
 
    for ( int i =0; i<255; i++)
    {
        lut[i] = (uchar)(temp*i*i+0.5);
    }
 
    for( int row =0; row <img->height; row++)
    {
        uchar *data = (uchar*)img->imageData+ row* img->widthStep;
        uchar *dstData = (uchar*)dst->imageData+ row* dst->widthStep;
 
        for ( int col = 0; col<img->width; col++)
        {
            for( int k=0; k<img->nChannels; k++)
            {
                uchar t1 = data[col*img->nChannels+k];                
                dstData[col*img->nChannels+k] = lut[t1];
            }
        }        
    }    
}
 

4、加Masaic算法(马赛克)

 

        在日常中有时候保密或其他需要将图像马赛克,下面的算法实现图像马赛克功能(原理:用中心像素来表示邻域像素)。

 

uchar getPixel( IplImage* img, int row, int col, int k)
{
    return ((uchar*)img->imageData + row* img->widthStep)[col*img->nChannels +k];
}
 
void setPixel( IplImage* img, int row, int col, int k, uchar val)
{
    ((uchar*)img->imageData + row* img->widthStep)[col*img->nChannels +k] = val;
}

// nSize:为尺寸大小,奇数
// 将邻域的值用中心像素的值替换
void Masic(IplImage* img, IplImage* dst, int nSize)
{
    int offset = (nSize-1)/2;
    for ( int row = offset; row <img->height - offset; row= row+offset)
    {
        for( int col= offset; col<img->width - offset; col = col+offset)
        {
            int val0 = getPixel(img, row, col, 0);
            int val1 = getPixel(img, row, col, 1);
            int val2 = getPixel(img, row, col, 2);
            for ( int m= -offset; m<offset; m++)
            {
                for ( int n=-offset; n<offset; n++)
                {
                    setPixel(dst, row+m, col+n, 0, val0);
                    setPixel(dst, row+m, col+n, 1, val1);
                    setPixel(dst, row+m, col+n, 2, val2);
                }
            }
        }
    }
}
 

5、曝光过度问题处理

 

      对于曝光过度问题,可以通过计算当前图像的反相(255-image),然后取当前图像和反相图像的较小者为当前像素位置的值。

// 过度曝光原理:图像翻转,然后求原图与反图的最小值
void ExporeOver(IplImage* img, IplImage* dst)
{
    for( int row =0; row <img->height; row++)
    {
        uchar *data = (uchar*)img->imageData+ row* img->widthStep;
        uchar *dstData = (uchar*)dst->imageData+ row* dst->widthStep;
 
        for ( int col = 0; col<img->width; col++)
        {
            for( int k=0; k<img->nChannels; k++)
            {
                uchar t1 = data[col*img->nChannels+k];
                uchar t2 = 255 - t1;
                dstData[col*img->nChannels+k] = min(t1,t2);
            }
        }        
    }
}
 

6、高反差保留

      高反差保留主要是将图像中颜色、明暗反差较大两部分的交界处保留下来,比如图像中有一个人和一块石头,那么石头的轮廓线和人的轮廓线以及面部、服装等有明显线条的地方会变被保留,儿其他大面积无明显明暗变化的地方则生成中灰色。其表达形式为:dst = r*(img - Blur(img))。

 

Mat HighPass(Mat img)
{
    Mat temp;
    GaussianBlur(img, temp,Size(7,7),1.6,1.6);
 
    int r=3;    
    Mat diff = img + r*(img-temp); //高反差保留算法
    return diff;
}

测试代码:

int main(int argc, char* argv[])
{
    const char* Path = "02.bmp";
    IplImage *img = cvLoadImage(Path,CV_LOAD_IMAGE_ANYCOLOR);
    IplImage *dst = cvCreateImage(cvGetSize(img), img->depth, img->nChannels);
    cout<<"输入你要选择的操作:"<<endl;
    cout<<"1、曝光过度"<<endl;
    cout<<"2、加马赛克"<<endl;
    cout<<"3、对数增强"<<endl;
    cout<<"4、指数增强"<<endl;
    cout<<"请输入你的选择:";
    int choice = 1;
    cin>>choice;
    switch (choice)
    {
    case 1: 
        ExporeOver(img, dst);   //这四个算法中总觉得某个算法有问题
        break;
    case 2: 
        Masic(img, dst, 21);
        break;
    case 3: 
        LogEnhance(img, dst);
        break;
    case 4:
        ExpEnhance(img, dst);
        break;
    default:
        cout<<"输入错误"<<endl;
        break;              
    }
    cvSaveImage("dst.jpg",dst);
    cvNamedWindow("SRC",1);
    cvNamedWindow("DST", 1);
    cvShowImage("SRC", img);
    cvShowImage("DST", dst);
    cvWaitKey();
    return 0;
}

7.拉普拉斯算子图像增强

使用中心为5的8邻域拉普拉斯算子与图像卷积可以达到锐化增强图像的目的。

拉普拉斯算子增强局部的图像对比度的opencv代码:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
 
using namespace cv;
 
int main(int argc, char *argv[])
{
    Mat image = imread("/Users/shandiangou/Downloads/lena.png");
    if (image.empty())
    {
        std::cout << "打开图片失败,请检查" << std::endl;
        return -1;
    }
    imshow("原图像", image);
    waitKey();
    Mat imageEnhance;
    Mat kernel = (Mat_<float>(3, 3) << 0, -1, 0, 0, 5, 0, 0, -1, 0);
    filter2D(image, imageEnhance, CV_8UC3, kernel);
    imshow("拉普拉斯算子图像增强效果", imageEnhance);
    waitKey();
    return 0;
}
 

参考博客:直方图均衡化、拉普拉斯算子图像增强、Gamma校正https://blog.csdn.net/sinat_28296297/article/details/77972023

                   OpenCV_基于Laplacian算子的图像边缘增强https://blog.csdn.net/icvpr/article/details/8502949

8.Gamma校正

       伽马变换主要用于图像的校正,将灰度过高或者灰度过低的图片进行修正,增强对比度。伽马变换对图像的修正作用其实就是通过增强低灰度或高灰度的细节实现的。

实现代码

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
 
#include <iostream>
 
using namespace cv;
using namespace std;
 
// Normalizes a given image into a value range between 0 and 255.
Mat norm_0_255(const Mat& src) {
    // Create and return normalized image:
    Mat dst;
    switch(src.channels()) {
        case 1:
            cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
            break;
        case 3:
            cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
            break;
        default:
            src.copyTo(dst);
            break;
    }
    return dst;
}
 
int main(int argc, const char *argv[]) {
    // Get filename to the source image:
    // Load image & get skin proportions:
    Mat image = imread("/Users/shandiangou/Downloads/guobao.jpeg");
    // Convert to floating point:
    Mat X;
    image.convertTo(X, CV_32FC1);
    //image.convertTo(X, CV_32F);
    // Start preprocessing:
    Mat I;
    float gamma = 3;
    pow(X, gamma, I);
    
    
    // Draw it on screen:
    imshow("Original Image", image);
    waitKey();
    imshow("Gamma correction image", norm_0_255(I));
    // Show the images:
    waitKey();
    // Success!
    return 0;  
}

暂时总结的就这8类,其他的之后再添

  • 39
    点赞
  • 348
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
OpenCV提供了多种图像增强方法,其中包括直方图均衡化和局部直方图均衡化。 直方图均衡化是一种将图像的像素值进行重新分布的方法,以增强图像的对比度。在OpenCV中,可以使用cv2.equalizeHist()函数来执行直方图均衡化。 局部直方图均衡化是在图像的不同区域应用不同的直方图均衡化方法,以处理不同区域之间的对比度差异。在OpenCV中,可以使用createCLAHE()函数来创建一个CLAHE对象,并使用apply()函数将其应用于图像。 除了直方图均衡化,OpenCV还提供了其他常用图像增强方法,例如左右翻转、随机裁剪和颜色变换。可以使用cv2.flip()函数进行左右翻转,使用cv2.resize()函数进行随机裁剪,并使用cv2.cvtColor()函数进行颜色变换。你也可以使用cv2.add()函数来调整亮度,cv2.multiply()函数来调整对比度,cv2.cvtColor()函数来调整饱和度和色调。 下面是一个示例代码,展示了如何使用OpenCV实现部分图像增强方法: ```python import cv2 import numpy as np from matplotlib import pyplot as plt # Load an image from a file filename = 'work/1.jpg' img = cv2.imread(filename) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Left-right flip flip_img = cv2.flip(img, 1) # Random crop crop_x = np.random.randint(0, img.shape - desired_width) crop_y = np.random.randint(0, img.shape - desired_height) crop_img = img[crop_y:crop_y+desired_height, crop_x:crop_x+desired_width] # Adjust brightness brightness_img = cv2.add(img, brightness_value) # Adjust contrast contrast_img = cv2.multiply(img, contrast_value) # Adjust saturation and hue hsv_img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) hsv_img[:,:,1 = cv2.multiply(hsv_img[:,:,1], saturation_value) hsv_img[:,:,0 = cv2.add(hsv_img[:,:,0], hue_value) saturation_hue_img = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2RGB) # Display the images plt.figure(figsize=(12, 8)) plt.subplot(231), plt.imshow(img), plt.title('Original') plt.subplot(232), plt.imshow(flip_img), plt.title('Left-right flip') plt.subplot(233), plt.imshow(crop_img), plt.title('Random crop') plt.subplot(234), plt.imshow(brightness_img), plt.title('Adjust brightness') plt.subplot(235), plt.imshow(contrast_img), plt.title('Adjust contrast') plt.subplot(236), plt.imshow(saturation_hue_img), plt.title('Adjust saturation and hue') plt.show() ``` 这个示例代码展示了如何使用OpenCV实现图像增强的一些常见方法,包括左右翻转、随机裁剪和调整亮度、对比度、饱和度和色调。 希望这个回答能够满足你的需求。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值