水下图像增强使用opencvc++



我正在尝试使用opencv增强水下视频图像。物体检测发生在HSV色彩空间中。在此之前,我一直在尝试找出消除水的颜色失真的技术。我读到的一种技术是对比拉伸RGB色彩空间,然后在HSI中拉伸饱和度和强度。

在尝试产生类似的工作,我想出了使用BGR规范化,然后转换为HSV和正常化的饱和度和值。这似乎并不能消除蓝色。是我的订单有问题,还是我在水下图像增强中遗漏了什么?

while(1){
//store image to matrix
capture.read(cameraFeed);
feedClone = cameraFeed.clone();
Mat HSV;
vector<Mat> channels;
vector<Mat> hsv_planes;
/*This is the part I am hoping to get feedback on*/
split(cameraFeed,channels);
normalize(channels[0], channels[0], 0, 255, NORM_MINMAX);
normalize(channels[1], channels[1], 0, 255, NORM_MINMAX);
normalize(channels[2], channels[2], 0, 255, NORM_MINMAX);
merge(channels,cameraFeed);     
cvtColor(cameraFeed,HSV,COLOR_BGR2HSV);
hsv_planes.clear();
split(HSV,hsv_planes);
normalize(hsv_planes[1], hsv_planes[1], 0, 255, NORM_MINMAX);
normalize(hsv_planes[2], hsv_planes[2], 0, 255, NORM_MINMAX);
merge(hsv_planes,HSV);
cvtColor(HSV,cameraFeed,COLOR_HSV2BGR);

/*This is what happens next and works perfectly out of water without the above adjustments*/
//This finds the specific color in the threshold         
cvtColor(cameraFeed,HSV,COLOR_BGR2HSV);
inRange(HSV,orange.getHSVmin(),orange.getHSVmax(),threshold);
//this function runs the threshold through 2 erodes and 2 dilates
//then a median blur (7,7)
morphOps(threshold);
//this tracks that image in the feed
trackFilteredObject(orange,threshold,HSV,feedClone);
}

看看这个Github存储库,它收集了Matlab脚本中的水下图像恢复和增强功能。它涵盖了不同的解决方案,如色彩空间处理、卷积神经网络(CNN)、介质传输、金字塔和结构化边缘检测器。你也可以用Octave运行它们。

它还提供了一个顶级脚本来运行这些方法。每个解决方案的结果都保存在磁盘上,允许对每种方法进行质量评估。您可以看到结果并从中选择一个。您唯一需要做的就是编写它的c++等价物。在这个存储库中还有一些Python水下图像恢复和增强功能。用c++编写Python代码要困难得多。

试试下面的代码。我有同样的问题,但它在很大程度上解决了这个问题。

#include "opencv2/opencv.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
    cout<<"Usage: ./executable input_image output_image n";
    if(argc!=3)
    {
        return 0;
    }

    int filterFactor = 1;
    Mat my_img = imread(argv[1]);
    Mat orig_img = my_img.clone();
    imshow("original",my_img);
    Mat simg;
    cvtColor(my_img, simg, CV_BGR2GRAY);
    long int N = simg.rows*simg.cols;
    int histo_b[256];
    int histo_g[256];
    int histo_r[256];
    for(int i=0; i<256; i++){
        histo_b[i] = 0;
        histo_g[i] = 0;
        histo_r[i] = 0;
    }
    Vec3b intensity;
    for(int i=0; i<simg.rows; i++){
        for(int j=0; j<simg.cols; j++){
            intensity = my_img.at<Vec3b>(i,j);
            histo_b[intensity.val[0]] = histo_b[intensity.val[0]] + 1;
            histo_g[intensity.val[1]] = histo_g[intensity.val[1]] + 1;
            histo_r[intensity.val[2]] = histo_r[intensity.val[2]] + 1;
        }
    }
    for(int i = 1; i<256; i++){
        histo_b[i] = histo_b[i] + filterFactor * histo_b[i-1];
        histo_g[i] = histo_g[i] + filterFactor * histo_g[i-1];
        histo_r[i] = histo_r[i] + filterFactor * histo_r[i-1];
    }
    int vmin_b=0;
    int vmin_g=0;
    int vmin_r=0;
    int s1 = 3;
    int s2 = 3;
    while(histo_b[vmin_b+1] <= N*s1/100){
        vmin_b = vmin_b +1;
    }
    while(histo_g[vmin_g+1] <= N*s1/100){
        vmin_g = vmin_g +1;
    }
    while(histo_r[vmin_r+1] <= N*s1/100){
        vmin_r = vmin_r +1;
    }
    int vmax_b = 255-1;
    int vmax_g = 255-1;
    int vmax_r = 255-1;
    while(histo_b[vmax_b-1]>(N-((N/100)*s2)))
    {   
        vmax_b = vmax_b-1;
    }
    if(vmax_b < 255-1){
        vmax_b = vmax_b+1;
    }
    while(histo_g[vmax_g-1]>(N-((N/100)*s2)))
    {   
        vmax_g = vmax_g-1;
    }
    if(vmax_g < 255-1){
        vmax_g = vmax_g+1;
    }
    while(histo_r[vmax_r-1]>(N-((N/100)*s2)))
    {   
        vmax_r = vmax_r-1;
    }
    if(vmax_r < 255-1){
        vmax_r = vmax_r+1;
    }
    for(int i=0; i<simg.rows; i++)
    {
        for(int j=0; j<simg.cols; j++)
        {
            intensity = my_img.at<Vec3b>(i,j);
            if(intensity.val[0]<vmin_b){
                intensity.val[0] = vmin_b;
            }
            if(intensity.val[0]>vmax_b){
                intensity.val[0]=vmax_b;
            }

            if(intensity.val[1]<vmin_g){
                intensity.val[1] = vmin_g;
            }
            if(intensity.val[1]>vmax_g){
                intensity.val[1]=vmax_g;
            }

            if(intensity.val[2]<vmin_r){
                intensity.val[2] = vmin_r;
            }
            if(intensity.val[2]>vmax_r){
                intensity.val[2]=vmax_r;
            }
            my_img.at<Vec3b>(i,j) = intensity;
        }
    }
    for(int i=0; i<simg.rows; i++){
        for(int j=0; j<simg.cols; j++){
            intensity = my_img.at<Vec3b>(i,j);
            intensity.val[0] = (intensity.val[0] - vmin_b)*255/(vmax_b-vmin_b);
            intensity.val[1] = (intensity.val[1] - vmin_g)*255/(vmax_g-vmin_g);
            intensity.val[2] = (intensity.val[2] - vmin_r)*255/(vmax_r-vmin_r);
            my_img.at<Vec3b>(i,j) = intensity;
        }
    }   

    // sharpen image using "unsharp mask" algorithm
    Mat blurred; double sigma = 1, threshold = 5, amount = 1;
    GaussianBlur(my_img, blurred, Size(), sigma, sigma);
    Mat lowContrastMask = abs(my_img - blurred) < threshold;
    Mat sharpened = my_img*(1+amount) + blurred*(-amount);
    my_img.copyTo(sharpened, lowContrastMask);    
    imshow("New Image",sharpened);
    waitKey(0);
    Mat comp_img;
    hconcat(orig_img, sharpened, comp_img);
    imwrite(argv[2], comp_img);
}

你试过阅读这个链接吗?http://answers.opencv.org/question/75510/how-to-make-auto-adjustmentsbrightness-and-contrast-for-image-android-opencv-image-correction/

void Utils::BrightnessAndContrastAuto(const cv::Mat &src, cv::Mat &dst, float clipHistPercent)
{
    CV_Assert(clipHistPercent >= 0);
    CV_Assert((src.type() == CV_8UC1) || (src.type() == CV_8UC3) || (src.type() == CV_8UC4));
    int histSize = 256;
    float alpha, beta;
    double minGray = 0, maxGray = 0;
    //to calculate grayscale histogram
    cv::Mat gray;
    if (src.type() == CV_8UC1) gray = src;
    else if (src.type() == CV_8UC3) cvtColor(src, gray, CV_BGR2GRAY);
    else if (src.type() == CV_8UC4) cvtColor(src, gray, CV_BGRA2GRAY);
    if (clipHistPercent == 0)
    {
        // keep full available range
        cv::minMaxLoc(gray, &minGray, &maxGray);
    }
    else
    {
        cv::Mat hist; //the grayscale histogram
        float range[] = { 0, 256 };
        const float* histRange = { range };
        bool uniform = true;
        bool accumulate = false;
        calcHist(&gray, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
        // calculate cumulative distribution from the histogram
        std::vector<float> accumulator(histSize);
        accumulator[0] = hist.at<float>(0);
        for (int i = 1; i < histSize; i++)
        {
            accumulator[i] = accumulator[i - 1] + hist.at<float>(i);
        }
        // locate points that cuts at required value
        float max = accumulator.back();
        clipHistPercent *= (max / 100.0); //make percent as absolute
        clipHistPercent /= 2.0; // left and right wings
        // locate left cut
        minGray = 0;
        while (accumulator[minGray] < clipHistPercent)
            minGray++;
        // locate right cut
        maxGray = histSize - 1;
        while (accumulator[maxGray] >= (max - clipHistPercent))
            maxGray--;
    }
    // current range
    float inputRange = maxGray - minGray;
    alpha = (histSize - 1) / inputRange;   // alpha expands current range to histsize range
    beta = -minGray * alpha;             // beta shifts current range so that minGray will go to 0
    // Apply brightness and contrast normalization
    // convertTo operates with saurate_cast
    src.convertTo(dst, -1, alpha, beta);
    // restore alpha channel from source 
    if (dst.type() == CV_8UC4)
    {
        int from_to[] = { 3, 3 };
        cv::mixChannels(&src, 4, &dst, 1, from_to, 1);
    }
    return;
}

相关内容

  • 没有找到相关文章

最新更新