196 lines
5.1 KiB
C++
196 lines
5.1 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "video_processing.h"
|
|
#include "brightness_detection.h"
|
|
#include "trace.h"
|
|
|
|
#include <math.h>
|
|
|
|
namespace webrtc {
|
|
|
|
VPMBrightnessDetection::VPMBrightnessDetection() :
|
|
_id(0)
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
VPMBrightnessDetection::~VPMBrightnessDetection()
|
|
{
|
|
}
|
|
|
|
WebRtc_Word32
|
|
VPMBrightnessDetection::ChangeUniqueId(const WebRtc_Word32 id)
|
|
{
|
|
_id = id;
|
|
return VPM_OK;
|
|
}
|
|
|
|
void
|
|
VPMBrightnessDetection::Reset()
|
|
{
|
|
_frameCntBright = 0;
|
|
_frameCntDark = 0;
|
|
}
|
|
|
|
WebRtc_Word32
|
|
VPMBrightnessDetection::ProcessFrame(const WebRtc_UWord8* frame,
|
|
const WebRtc_UWord32 width,
|
|
const WebRtc_UWord32 height,
|
|
const VideoProcessingModule::FrameStats& stats)
|
|
{
|
|
if (frame == NULL)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoPreocessing, _id, "Null frame pointer");
|
|
return VPM_PARAMETER_ERROR;
|
|
}
|
|
|
|
if (width == 0 || height == 0)
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoPreocessing, _id, "Invalid frame size");
|
|
return VPM_PARAMETER_ERROR;
|
|
}
|
|
|
|
if (!VideoProcessingModule::ValidFrameStats(stats))
|
|
{
|
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoPreocessing, _id, "Invalid frame stats");
|
|
return VPM_PARAMETER_ERROR;
|
|
}
|
|
|
|
const WebRtc_UWord8 frameCntAlarm = 2;
|
|
|
|
// Get proportion in lowest bins
|
|
WebRtc_UWord8 lowTh = 20;
|
|
float propLow = 0;
|
|
for (WebRtc_UWord32 i = 0; i < lowTh; i++)
|
|
{
|
|
propLow += stats.hist[i];
|
|
}
|
|
propLow /= stats.numPixels;
|
|
|
|
// Get proportion in highest bins
|
|
unsigned char highTh = 230;
|
|
float propHigh = 0;
|
|
for (WebRtc_UWord32 i = highTh; i < 256; i++)
|
|
{
|
|
propHigh += stats.hist[i];
|
|
}
|
|
propHigh /= stats.numPixels;
|
|
|
|
if(propHigh < 0.4)
|
|
{
|
|
if (stats.mean < 90 || stats.mean > 170)
|
|
{
|
|
// Standard deviation of Y
|
|
float stdY = 0;
|
|
for (WebRtc_UWord32 h = 0; h < height; h += (1 << stats.subSamplHeight))
|
|
{
|
|
WebRtc_UWord32 row = h*width;
|
|
for (WebRtc_UWord32 w = 0; w < width; w += (1 << stats.subSamplWidth))
|
|
{
|
|
stdY += (frame[w + row] - stats.mean) * (frame[w + row] - stats.mean);
|
|
}
|
|
}
|
|
stdY = sqrt(stdY / stats.numPixels);
|
|
|
|
// Get percentiles
|
|
WebRtc_UWord32 sum = 0;
|
|
WebRtc_UWord32 medianY = 140;
|
|
WebRtc_UWord32 perc05 = 0;
|
|
WebRtc_UWord32 perc95 = 255;
|
|
float posPerc05 = stats.numPixels * 0.05f;
|
|
float posMedian = stats.numPixels * 0.5f;
|
|
float posPerc95 = stats.numPixels * 0.95f;
|
|
for (WebRtc_UWord32 i = 0; i < 256; i++)
|
|
{
|
|
sum += stats.hist[i];
|
|
|
|
if (sum < posPerc05)
|
|
{
|
|
perc05 = i; // 5th perc
|
|
}
|
|
if (sum < posMedian)
|
|
{
|
|
medianY = i; // 50th perc
|
|
}
|
|
if (sum < posPerc95)
|
|
{
|
|
perc95 = i; // 95th perc
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check if image is too dark
|
|
if ((stdY < 55) && (perc05 < 50))
|
|
{
|
|
if (medianY < 60 || stats.mean < 80 || perc95 < 130 || propLow > 0.20)
|
|
{
|
|
_frameCntDark++;
|
|
}
|
|
else
|
|
{
|
|
_frameCntDark = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_frameCntDark = 0;
|
|
}
|
|
|
|
// Check if image is too bright
|
|
if ((stdY < 52) && (perc95 > 200) && (medianY > 160))
|
|
{
|
|
if (medianY > 185 || stats.mean > 185 || perc05 > 140 || propHigh > 0.25)
|
|
{
|
|
_frameCntBright++;
|
|
}
|
|
else
|
|
{
|
|
_frameCntBright = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_frameCntBright = 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
_frameCntDark = 0;
|
|
_frameCntBright = 0;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
_frameCntBright++;
|
|
_frameCntDark = 0;
|
|
}
|
|
|
|
if (_frameCntDark > frameCntAlarm)
|
|
{
|
|
return VideoProcessingModule::kDarkWarning;
|
|
}
|
|
else if (_frameCntBright > frameCntAlarm)
|
|
{
|
|
return VideoProcessingModule::kBrightWarning;
|
|
}
|
|
else
|
|
{
|
|
return VideoProcessingModule::kNoWarning;
|
|
}
|
|
}
|
|
|
|
} //namespace
|