【问题标题】:Underwater image enhancement using opencv c++使用opencv c ++进行水下图像增强
【发布时间】:2014-05-09 09:11:08
【问题描述】:

我正在尝试使用 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);
}

【问题讨论】:

    标签: c++ image opencv image-enhancement


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      你试过阅读这个链接吗? 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;
      }
      

      【讨论】:

        【解决方案3】:

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

        #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);
        }
        

        查看here了解更多详情。

        【讨论】:

          猜你喜欢
          • 2018-04-14
          • 2015-04-24
          • 2019-11-10
          • 2013-10-19
          • 1970-01-01
          • 2020-03-15
          • 1970-01-01
          • 2020-11-24
          • 2014-09-12
          相关资源
          最近更新 更多