多尺度的图像细节提升multiScaleSharpen实现方法

图像增强:多尺度的图像细节提升(multi-scale detail boosting)实现方法

 

 

 

#include <iostream>    
#include <opencv2\opencv.hpp>    
#include <opencv2\highgui\highgui.hpp>    
using namespace std;
using namespace cv;
 
cv::Mat multiScaleSharpen(cv::Mat Src, int Radius)
{
    int rows = Src.rows;
    int cols = Src.cols;
    int cha = Src.channels();
    cv::Mat B1, B2, B3;
    GaussianBlur(Src, B1, Size(Radius, Radius), 1.0, 1.0);//高斯模糊
    GaussianBlur(Src, B2, Size(Radius*2-1, Radius*2-1), 2.0, 2.0);
    GaussianBlur(Src, B3, Size(Radius*4-1, Radius*4-1), 4.0, 4.0);
 
    double w1 = 0.5;
    double w2 = 0.5;
    double w3 = 0.25;
 
    cv::Mat dest = cv::Mat::zeros(Src.size(), Src.type());
    for (size_t i = 0; i < rows; i++)
    {
        uchar* src_ptr = Src.ptr<uchar>(i);
        uchar* dest_ptr = dest.ptr<uchar>(i);
        uchar* B1_ptr = B1.ptr<uchar>(i);
        uchar* B2_ptr = B2.ptr<uchar>(i);
        uchar* B3_ptr = B3.ptr<uchar>(i);
        for (size_t j = 0; j < cols; j++)
        {
            for (size_t c = 0; c < cha; c++)
            {
                int  D1 = src_ptr[3*j+c] - B1_ptr[3 * j + c];
                int  D2 = B1_ptr[3 * j + c] - B2_ptr[3 * j + c];
                int  D3 = B2_ptr[3 * j + c] - B3_ptr[3 * j + c];
                int  sign = (D1 > 0) ? 1 : -1;
                dest_ptr[3 * j + c] = saturate_cast<uchar>((1 - w1*sign)*D1 - w2*D2 + w3*D3 + src_ptr[3 * j + c]);
            }
        }
    }
    return dest;
}
 
int main(int argc)
{
    Mat src = imread("image\\test.jpg");
    cv::imshow("src", src);
    cvWaitKey(100);
 
    cv::Mat dest=multiScaleSharpen(src,5);
    cv::imshow("dest", dest);
 
    cvWaitKey(0);
    return 0;
}

 

 
作为一种简单可行的方法,是有效果的。并入GOCvHelper库中,并且向OpenCV进行推送。

 

 

 
为了进行pr的资料准备,需要做以下研究:
1、算法原理,比较能够将清楚的地方;(OK继续)
2、此类代码放在哪里比较合适,并且确保编译正确;
3、完善文档,提炼价值。
 
该算法来自论文
DARK IMAGE ENHANCEMENT BASED ON PAIRWISE TARGET CONTRAST AND MULTI-SCALE DETAIL BOOSTING
的第2.3节

论文的核心思想类似于Retinex,使用了三个尺度的高斯模糊,再和原图做减法,获得不同程度的细节信息,然后通过一定的组合方式把这些细节信息融合到原图中,从而得到加强原图信息的能力。值得一提的就是对D1的系数做了特殊的处理,算法的编码简单、效果明显。

对应的python实现

 

# -*- coding: utf-8 -*-

import cv2
import numpy as np
from numpy import uint8
from numpy import float32
from numpy import hstack

def multiScaleSharpen(img ,radius):

    h,w,chan = img.shape
    GaussBlue1 = np.zeros(img.shape,dtype = uint8)
    GaussBlue2 = np.zeros(img.shape, dtype=uint8)
    GaussBlue3 = np.zeros(img.shape, dtype=uint8)
    Dest_float_img = np.zeros(img.shape, dtype=float32)
    Dest_img = np.zeros(img.shape, dtype=uint8)

    w1 = 0.5
    w2 = 0.5
    w3 = 0.25

    GaussBlue1 = cv2.GaussianBlur(img,(radius,radius),1)
    GaussBlue2 = cv2.GaussianBlur(img,(radius*2-1,radius*2-1),2)
    GaussBlue3 = cv2.GaussianBlur(img,(radius*4-1,radius*4-1),4)

    for i in range(0,h):
        for j in range(0,w):
            for k in range(0,chan):
                Src = img.item(i,j,k)
                D1 = Src-GaussBlue1.item(i,j,k)
                D2 = GaussBlue1.item(i,j,k) - GaussBlue2.item(i,j,k)
                D3 = GaussBlue2.item(i,j,k) - GaussBlue3.item(i,j,k)
                if(D1 > 0):
                    sig = 1
                else:
                    sig = -1
                Dest_float_img.itemset((i,j,k),(1-w1*sig)*D1+w2*D2+w3*D3+Src)

    Dest_img = cv2.convertScaleAbs(Dest_float_img)
    return Dest_img

if __name__ == '__main__':
    img = cv2.imread("175_result.bmp")
    #img = cv2.imread("128.jpg")
    multiScaleSharpen_out = np.zeros(img.shape, dtype=uint8)
    multiScaleSharpen_out = multiScaleSharpen(img,5)#jishu
    cv2.imwrite("multiScaleSharpen_175_result.bmp", multiScaleSharpen_out)

OpenCV自己是否有Shappen的东西?值得研究。

#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
using namespace cv;
using namespace std;
int sharpenRadius = 1;
Mat image, sharpen;
const char* window_name1 = "multiScaleSharpen";
Mat multiScaleSharpen(Mat Src, int Radius)
{
    int rows = Src.rows;
    int cols = Src.cols;
    int cha = Src.channels();
    Mat B1, B2, B3;
    GaussianBlur(Src, B1, Size(Radius, Radius), 1.0, 1.0);
    GaussianBlur(Src, B2, Size(Radius * 2 - 1, Radius * 2 - 1), 2.0, 2.0);
    GaussianBlur(Src, B3, Size(Radius * 4 - 1, Radius * 4 - 1), 4.0, 4.0);
    double w1 = 0.5;
    double w2 = 0.5;
    double w3 = 0.25;
    cv::Mat dest = cv::Mat::zeros(Src.size(), Src.type());
    for (size_t i = 0; i < rows; i++)
    {
        uchar* src_ptr = Src.ptr<uchar>(i);
        uchar* dest_ptr = dest.ptr<uchar>(i);
        uchar* B1_ptr = B1.ptr<uchar>(i);
        uchar* B2_ptr = B2.ptr<uchar>(i);
        uchar* B3_ptr = B3.ptr<uchar>(i);
        for (size_t j = 0; j < cols; j++)
        {
            for (size_t c = 0; c < cha; c++)
            {
                int  D1 = src_ptr[3 * j + c] - B1_ptr[3 * j + c];
                int  D2 = B1_ptr[3 * j + c] - B2_ptr[3 * j + c];
                int  D3 = B2_ptr[3 * j + c] - B3_ptr[3 * j + c];
                int  sign = (D1 > 0) ? 1 : -1;
                dest_ptr[3 * j + c] = saturate_cast<uchar>((1 - w1 * sign)*D1 - w2 * D2 + w3 * D3 + src_ptr[3 * j + c]);
            }
        }
    }
    return dest;
}
// define a trackbar callback
static void onTrackbar(int, void*)
{
    sharpen = multiScaleSharpen(image, sharpenRadius *2+1);
    imshow(window_name1, sharpen);
}
static void help(const char** argv)
{
    printf("\nThis sample demonstrates multiScaleSharpen detection\n"
           "Call:\n"
           "    %s [image_name -- Default is lena.jpg]\n\n", argv[0]);
}
const char* keys =
{
    "{help h||}{@image |lena.jpg|input image name}"
};
int main( int argc, const char** argv )
{
    help(argv);
    CommandLineParser parser(argc, argv, keys);
    string filename = parser.get<string>(0);
    image = imread(samples::findFile(filename), IMREAD_COLOR);
    if(image.empty())
    {
        printf("Cannot read image file: %s\n", filename.c_str());
        help(argv);
        return -1;
    }
    // Create a window
    namedWindow(window_name1, 1);
    // create a toolbar
    createTrackbar("Canny threshold default", window_name1, &sharpenRadius, 7, onTrackbar);
    // Show the image
    onTrackbar(0, 0);
    // Wait for a key stroke; the same function arranges events processing
    waitKey(0);
    return 0;}
给提供了:
void Sharpen(const Mat& myImage,Mat& Result)
{
  //! [8_bit]
    CV_Assert(myImage.depth() == CV_8U);  // accept only uchar images
  //! [8_bit]

  //! [create_channels]
    const int nChannels = myImage.channels();
    Result.create(myImage.size(),myImage.type());
  //! [create_channels]

  //! [basic_method_loop]
    for(int j = 1 ; j < myImage.rows-1; ++j)
    {
        const uchar* previous = myImage.ptr<uchar>(j - 1);
        const uchar* current  = myImage.ptr<uchar>(j    );
        const uchar* next     = myImage.ptr<uchar>(j + 1);

        uchar* output = Result.ptr<uchar>(j);

        for(int i= nChannels;i < nChannels*(myImage.cols-1); ++i)
        {
            *output++ = saturate_cast<uchar>(5*current[i]
                         -current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
        }
    }
  //! [basic_method_loop]

  //! [borders]
    Result.row(0).setTo(Scalar(0));
    Result.row(Result.rows-1).setTo(Scalar(0));
    Result.col(0).setTo(Scalar(0));
    Result.col(Result.cols-1).setTo(Scalar(0));
  //! [borders]
}

 

posted on 2022-12-22 12:17  jsxyhelu  阅读(211)  评论(0编辑  收藏  举报

导航