C++ 基于opencvc++;

C++ 基于opencvc++;,c++,image,opencv,image-enhancement,C++,Image,Opencv,Image Enhancement,我正在尝试使用opencv增强水下视频图像。目标检测在HSV颜色空间中进行。在此之前,我一直在尝试找出消除水的颜色失真的技术。我读到的一种技术是对比度拉伸RGB颜色空间,然后在HSI中拉伸饱和度和强度 为了产生类似的效果,我在BGR上使用normalize,然后转换为HSV,并对饱和度和值进行规范化。这似乎不能消除蓝色。我的订单有问题吗?或者我在水下图像增强中遗漏了什么 while(1){ //store image to matrix capture.read(cameraFeed); fee

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

为了产生类似的效果,我在BGR上使用normalize,然后转换为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);
}
while(1){
//将图像存储到矩阵
捕获.读取(cameraFeed);
feedClone=cameraFeed.clone();
Mat-HSV;
矢量通道;
矢量hsv_平面;
/*这是我希望得到反馈的部分*/
分割(摄像机馈送、通道);
正常化(通道[0],通道[0],0,255,标准值_最小值);
正常化(通道[1],通道[1],0,255,标准值_最小值);
正常化(通道[2],通道[2],0,255,NORM_MINMAX);
合并(频道、摄影机提要);
cvtColor(cameraFeed、HSV、COLOR_BGR2HSV);
hsv_平面。清除();
拆分(HSV、HSV_平面);
规格化(hsv_平面[1],hsv_平面[1],0,255,NORM_MINMAX);
规格化(hsv_平面[2],hsv_平面[2],0,255,NORM_MINMAX);
合并(hsv_平面,hsv);
cvtColor(HSV、cameraFeed、COLOR_HSV2BGR);
/*这就是接下来发生的事情,在没有上述调整的情况下,它在水外工作得非常完美*/
//这将在阈值中查找特定颜色
cvtColor(cameraFeed、HSV、COLOR_BGR2HSV);
inRange(HSV,orange.getHSVmin(),orange.getHSVmax(),阈值);
//此函数通过2次侵蚀和2次扩张运行阈值
//然后是中值模糊(7,7)
morphOps(阈值);
//这将跟踪提要中的图像
trackFilteredObject(橙色、阈值、HSV、feedClone);
}

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

#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);
}
#包括“opencv2/opencv.hpp”
#包括
使用名称空间std;
使用名称空间cv;
int main(int argc,字符**argv)
{

你有没有试过阅读这个链接

void Utils::BrightnessAndContrastAuto(常量cv::Mat&src,cv::Mat&dst,浮点clipHistPercent)
{
CV_断言(clipHistPercent>=0);
CV_断言((src.type()==CV_8UC1)| |(src.type()==CV_8UC3)| |(src.type()==CV_8UC4));
int histSize=256;
浮动α,β;
double minGray=0,maxGray=0;
//计算灰度直方图
cv::席灰色;
如果(src.type()==CV_8UC1)gray=src;
否则,如果(src.type()==CV_8UC3)cvtColor(src,gray,CV_bgr2 gray);
否则如果(src.type()==CV_8UC4)cvt颜色(src,灰色,CV_BGRA2GRAY);
如果(clipHistPercent==0)
{
//保持全部可用范围
cv::minMaxLoc(灰色、明雷和maxGray);
}
其他的
{
cv::Mat hist;//灰度直方图
浮动范围[]={0,256};
常量浮点*histRange={range};
布尔一致=真;
布尔累积=假;
calcHist(&gray,1,0,cv::Mat(),hist,1,&histSize,&histRange,统一,累积);
//根据直方图计算累积分布
std::向量累加器(histSize);
累加器[0]=在(0)处的历史记录;
对于(int i=1;i=(最大-clipHistPercent))
马克斯格雷--;
}
//电流范围
float inputRange=maxGray-minGray;
alpha=(histSize-1)/inputRange;//alpha将当前范围扩展到histSize范围
beta=-minGray*alpha;//beta移动当前范围,使minGray变为0
//应用亮度和对比度标准化
//convertTo与saurate_cast合作
src.convertTo(dst,-1,alpha,beta);
//从源还原alpha通道
如果(dst.type()=CV_8UC4)
{
int从_到[]={3,3};
cv::混合通道(&src,4,&dst,1,从_到,1);
}
返回;
}
看看这个Github,它用Matlab脚本收集了一系列水下图像恢复和增强。它涵盖了不同的解决方案,如颜色空间处理、卷积神经网络(CNN)、介质传输、金字塔和结构化边缘检测器。您也可以使用倍频程运行它们

它还提供了一个顶部脚本来完全运行这些方法。每个解决方案的结果都保存在磁盘上,允许对每个方法进行质量评估。您可以看到结果并选择其中一个。您需要做的就是写它的C++等效。还有一些Python水下图像恢复和增强。Python代码在C++中是比较难编写的。

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