C++ 基于opencvc++;
我正在尝试使用opencv增强水下视频图像。目标检测在HSV颜色空间中进行。在此之前,我一直在尝试找出消除水的颜色失真的技术。我读到的一种技术是对比度拉伸RGB颜色空间,然后在HSI中拉伸饱和度和强度 为了产生类似的效果,我在BGR上使用normalize,然后转换为HSV,并对饱和度和值进行规范化。这似乎不能消除蓝色。我的订单有问题吗?或者我在水下图像增强中遗漏了什么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
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;
}