mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 12:05:23 +00:00
update
This commit is contained in:
parent
a62ed45a0b
commit
e49075290d
5 changed files with 80 additions and 40 deletions
|
@ -993,8 +993,8 @@ public:
|
|||
m_tracker.set_saturation_threshold(gem_num, config->saturation_threshold);
|
||||
}
|
||||
|
||||
m_tracker.set_min_radius(static_cast<f32>(g_cfg_move.min_radius.get() / g_cfg_move.min_radius.max));
|
||||
m_tracker.set_max_radius(static_cast<f32>(g_cfg_move.max_radius.get() / g_cfg_move.max_radius.max));
|
||||
m_tracker.set_min_radius(static_cast<f32>(g_cfg_move.min_radius) / 100.0f);
|
||||
m_tracker.set_max_radius(static_cast<f32>(g_cfg_move.max_radius) / 100.0f);
|
||||
|
||||
// Process camera image
|
||||
m_tracker.process_image();
|
||||
|
|
|
@ -26,8 +26,8 @@ struct cfg_ps_moves final : cfg::node
|
|||
cfg_ps_move move3{ this, "PS Move 3" };
|
||||
cfg_ps_move move4{ this, "PS Move 4" };
|
||||
|
||||
cfg::_float<0, 100> min_radius{ this, "Minimum Radius", 1.0f, true }; // Percentage of image width
|
||||
cfg::_float<0, 100> max_radius{ this, "Maximum Radius", 10.0f, true }; // Percentage of image width
|
||||
cfg::_float<0, 50> min_radius{ this, "Minimum Radius", 1.0f, true }; // Percentage of image width
|
||||
cfg::_float<0, 50> max_radius{ this, "Maximum Radius", 10.0f, true }; // Percentage of image width
|
||||
|
||||
std::array<cfg_ps_move*, 4> move{ &move1, &move2, &move3, &move4 };
|
||||
|
||||
|
|
|
@ -277,9 +277,9 @@ void ps_move_tracker<DiagnosticsEnabled>::process_hues()
|
|||
|
||||
for (u32 x = 0; x < width; x++, rgba += 4, hsv += 3)
|
||||
{
|
||||
const float r = rgba[0] / 255.0f;
|
||||
const float g = rgba[1] / 255.0f;
|
||||
const float b = rgba[2] / 255.0f;
|
||||
const f32 r = rgba[0] / 255.0f;
|
||||
const f32 g = rgba[1] / 255.0f;
|
||||
const f32 b = rgba[2] / 255.0f;
|
||||
const auto [hue, saturation, value] = rgb_to_hsv(r, g, b);
|
||||
|
||||
hsv[0] = static_cast<u8>(hue / 2);
|
||||
|
@ -296,23 +296,51 @@ void ps_move_tracker<DiagnosticsEnabled>::process_hues()
|
|||
}
|
||||
|
||||
#ifdef HAVE_OPENCV
|
||||
static bool is_circular_contour(const std::vector<cv::Point>& contour, float& area)
|
||||
static bool is_circular_contour(const std::vector<cv::Point>& contour, f32& area)
|
||||
{
|
||||
std::vector<cv::Point> approx;
|
||||
cv::approxPolyDP(contour, approx, 0.01 * cv::arcLength(contour, true), true);
|
||||
if (approx.size() < 8ULL) return false;
|
||||
|
||||
area = static_cast<float>(cv::contourArea(contour));
|
||||
area = static_cast<f32>(cv::contourArea(contour));
|
||||
if (area < 30.0f) return false;
|
||||
|
||||
cv::Point2f center;
|
||||
float radius;
|
||||
f32 radius;
|
||||
cv::minEnclosingCircle(contour, center, radius);
|
||||
if (radius < 5.0f) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
void ps_move_tracker<DiagnosticsEnabled>::draw_sphere_size_range(f32 result_radius)
|
||||
{
|
||||
if constexpr (!DiagnosticsEnabled) return;
|
||||
if (!m_draw_overlays) return;
|
||||
|
||||
// Map memory
|
||||
cv::Mat rgba(cv::Size(m_width, m_height), CV_8UC4, m_image_rgba_contours.data(), 0);
|
||||
|
||||
// Draw result, min and max radius
|
||||
const f32 min_radius = m_min_radius * m_width;
|
||||
const f32 max_radius = m_max_radius * m_width;
|
||||
const f32 min_radius_clamped = std::max(0.0f, std::min(min_radius, max_radius));
|
||||
const cv::Point2f center = cv::Point2f(m_width - 1 - max_radius, max_radius);
|
||||
if (result_radius > 0.0f)
|
||||
{
|
||||
cv::circle(rgba, center, static_cast<int>(result_radius), cv::Scalar(255, 0, 0, 255), cv::FILLED);
|
||||
}
|
||||
if (min_radius_clamped > 0.0f && min_radius_clamped <= max_radius)
|
||||
{
|
||||
cv::circle(rgba, center, static_cast<int>(min_radius_clamped), cv::Scalar(0, 0, 0, 255), cv::FILLED);
|
||||
}
|
||||
if (max_radius > min_radius_clamped)
|
||||
{
|
||||
cv::circle(rgba, center, static_cast<int>(max_radius), cv::Scalar(0, 0, 0, 255), 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u32 index)
|
||||
{
|
||||
|
@ -363,7 +391,7 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
cv::findContours(binary, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);
|
||||
for (auto it = contours.begin(); it != contours.end();)
|
||||
{
|
||||
float area;
|
||||
f32 area;
|
||||
if (is_circular_contour(*it, area))
|
||||
{
|
||||
it = contours.erase(it);
|
||||
|
@ -384,6 +412,11 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
if (all_contours.empty())
|
||||
{
|
||||
set_valid(info, index, false);
|
||||
|
||||
if constexpr (DiagnosticsEnabled)
|
||||
{
|
||||
draw_sphere_size_range(0.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -393,24 +426,24 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
std::vector<cv::Point2f> centers;
|
||||
centers.reserve(all_contours.size());
|
||||
|
||||
std::vector<float> radii;
|
||||
std::vector<f32> radii;
|
||||
radii.reserve(all_contours.size());
|
||||
|
||||
const f32 min_radius = m_min_radius * width;
|
||||
const f32 max_radius = m_max_radius * width;
|
||||
|
||||
usz best_index = umax;
|
||||
float best_area = 0.0f;
|
||||
f32 best_area = 0.0f;
|
||||
for (usz i = 0; i < all_contours.size(); i++)
|
||||
{
|
||||
const std::vector<cv::Point>& contour = all_contours[i];
|
||||
float area;
|
||||
f32 area;
|
||||
if (!is_circular_contour(contour, area))
|
||||
continue;
|
||||
|
||||
// Get center and radius
|
||||
cv::Point2f center;
|
||||
float radius;
|
||||
f32 radius;
|
||||
cv::minEnclosingCircle(contour, center, radius);
|
||||
|
||||
// Filter radius
|
||||
|
@ -431,6 +464,11 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
if (best_index == umax)
|
||||
{
|
||||
set_valid(info, index, false);
|
||||
|
||||
if constexpr (DiagnosticsEnabled)
|
||||
{
|
||||
draw_sphere_size_range(0.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -438,7 +476,7 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
const f32 sphere_radius_pixels = radii[best_index];
|
||||
constexpr f32 focal_length_mm = 3.5f; // Based on common webcam specs
|
||||
constexpr f32 sensor_width_mm = 3.6f; // Based on common webcam specs
|
||||
const f32 image_width_pixels = static_cast<float>(width);
|
||||
const f32 image_width_pixels = static_cast<f32>(width);
|
||||
const f32 focal_length_pixels = (focal_length_mm * image_width_pixels) / sensor_width_mm;
|
||||
const f32 distance_mm = (focal_length_pixels * CELL_GEM_SPHERE_RADIUS_MM) / sphere_radius_pixels;
|
||||
|
||||
|
@ -472,6 +510,8 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
if (!m_draw_contours && !m_draw_overlays) [[likely]]
|
||||
return;
|
||||
|
||||
draw_sphere_size_range(info.radius);
|
||||
|
||||
// Map memory
|
||||
cv::Mat rgba(cv::Size(width, height), CV_8UC4, m_image_rgba_contours.data(), 0);
|
||||
|
||||
|
@ -499,11 +539,11 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
for (usz i = 0; i < centers.size(); i++)
|
||||
{
|
||||
const cv::Point2f& center = centers[i];
|
||||
const float radius = radii[i];
|
||||
const f32 radius = radii[i];
|
||||
|
||||
cv::circle(rgba, center, static_cast<int>(radius), circle_color, 1);
|
||||
cv::line(rgba, center + cv::Point2f(-2, 0), center + cv::Point2f(2, 0), center_color, 1);
|
||||
cv::line(rgba, center + cv::Point2f(0, -2), center + cv::Point2f(0, 2), center_color, 1);
|
||||
cv::line(rgba, center + cv::Point2f(-2.0f, 0.0f), center + cv::Point2f(2.0f, 0.0f), center_color, 1);
|
||||
cv::line(rgba, center + cv::Point2f(0.0f, -2.0f), center + cv::Point2f(0.0f, 2.0f), center_color, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -525,16 +565,16 @@ void ps_move_tracker<DiagnosticsEnabled>::process_contours(ps_move_info& info, u
|
|||
#endif
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
std::tuple<u8, u8, u8> ps_move_tracker<DiagnosticsEnabled>::hsv_to_rgb(u16 hue, float saturation, float value)
|
||||
std::tuple<u8, u8, u8> ps_move_tracker<DiagnosticsEnabled>::hsv_to_rgb(u16 hue, f32 saturation, f32 value)
|
||||
{
|
||||
const float h = hue / 60.0f;
|
||||
const float chroma = value * saturation;
|
||||
const float x = chroma * (1.0f - std::abs(std::fmod(h, 2.0f) - 1.0f));
|
||||
const float m = value - chroma;
|
||||
const f32 h = hue / 60.0f;
|
||||
const f32 chroma = value * saturation;
|
||||
const f32 x = chroma * (1.0f - std::abs(std::fmod(h, 2.0f) - 1.0f));
|
||||
const f32 m = value - chroma;
|
||||
|
||||
float r = 0.0f;
|
||||
float g = 0.0f;
|
||||
float b = 0.0f;
|
||||
f32 r = 0.0f;
|
||||
f32 g = 0.0f;
|
||||
f32 b = 0.0f;
|
||||
|
||||
switch (static_cast<int>(std::ceil(h)))
|
||||
{
|
||||
|
@ -581,12 +621,12 @@ std::tuple<u8, u8, u8> ps_move_tracker<DiagnosticsEnabled>::hsv_to_rgb(u16 hue,
|
|||
}
|
||||
|
||||
template <bool DiagnosticsEnabled>
|
||||
std::tuple<s16, float, float> ps_move_tracker<DiagnosticsEnabled>::rgb_to_hsv(float r, float g, float b)
|
||||
std::tuple<s16, f32, f32> ps_move_tracker<DiagnosticsEnabled>::rgb_to_hsv(f32 r, f32 g, f32 b)
|
||||
{
|
||||
const float cmax = std::max({r, g, b}); // V (of HSV)
|
||||
const float cmin = std::min({r, g, b});
|
||||
const float delta = cmax - cmin;
|
||||
const float saturation = cmax ? (delta / cmax) : 0.0f; // S (of HSV)
|
||||
const f32 cmax = std::max({r, g, b}); // V (of HSV)
|
||||
const f32 cmin = std::min({r, g, b});
|
||||
const f32 delta = cmax - cmin;
|
||||
const f32 saturation = cmax ? (delta / cmax) : 0.0f; // S (of HSV)
|
||||
|
||||
s16 hue; // H (of HSV)
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ public:
|
|||
const std::vector<u8>& gray() { return m_image_gray; }
|
||||
const std::vector<u8>& binary(u32 index) { return ::at32(m_image_binary, index); }
|
||||
|
||||
static std::tuple<u8, u8, u8> hsv_to_rgb(u16 hue, float saturation, float value);
|
||||
static std::tuple<s16, float, float> rgb_to_hsv(float r, float g, float b);
|
||||
static std::tuple<u8, u8, u8> hsv_to_rgb(u16 hue, f32 saturation, f32 value);
|
||||
static std::tuple<s16, f32, f32> rgb_to_hsv(f32 r, f32 g, f32 b);
|
||||
|
||||
private:
|
||||
struct ps_move_config
|
||||
|
@ -73,6 +73,8 @@ private:
|
|||
|
||||
void set_valid(ps_move_info& info, u32 index, bool valid);
|
||||
|
||||
void draw_sphere_size_range(f32 result_radius);
|
||||
|
||||
u32 m_width = 0;
|
||||
u32 m_height = 0;
|
||||
s32 m_format = 0;
|
||||
|
|
|
@ -362,8 +362,7 @@ void ps_move_tracker_dialog::update_saturation_threshold(bool update_slider)
|
|||
}
|
||||
void ps_move_tracker_dialog::update_min_radius(bool update_slider)
|
||||
{
|
||||
const f32 min_radius = std::clamp(g_cfg_move.min_radius / min_radius_conversion, g_cfg_move.min_radius.min, g_cfg_move.min_radius.max);
|
||||
ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(min_radius));
|
||||
ui->minRadiusGb->setTitle(tr("Min Radius: %0 %").arg(g_cfg_move.min_radius));
|
||||
|
||||
if (update_slider)
|
||||
{
|
||||
|
@ -373,8 +372,7 @@ void ps_move_tracker_dialog::update_min_radius(bool update_slider)
|
|||
|
||||
void ps_move_tracker_dialog::update_max_radius(bool update_slider)
|
||||
{
|
||||
const f32 max_radius = std::clamp(g_cfg_move.max_radius / max_radius_conversion, g_cfg_move.max_radius.min, g_cfg_move.max_radius.max);
|
||||
ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(max_radius));
|
||||
ui->maxRadiusGb->setTitle(tr("Max Radius: %0 %").arg(g_cfg_move.max_radius));
|
||||
|
||||
if (update_slider)
|
||||
{
|
||||
|
@ -467,8 +465,8 @@ void ps_move_tracker_dialog::process_camera_frame()
|
|||
}
|
||||
|
||||
m_ps_move_tracker->set_image_data(m_frame_frozen ? m_image_data_frozen.data() : m_image_data.data(), m_image_data.size(), width, height, m_camera_handler->format());
|
||||
m_ps_move_tracker->set_min_radius(static_cast<f32>(g_cfg_move.min_radius.get() / g_cfg_move.min_radius.max));
|
||||
m_ps_move_tracker->set_max_radius(static_cast<f32>(g_cfg_move.max_radius.get() / g_cfg_move.max_radius.max));
|
||||
m_ps_move_tracker->set_min_radius(static_cast<f32>(g_cfg_move.min_radius) / 100.0f);
|
||||
m_ps_move_tracker->set_max_radius(static_cast<f32>(g_cfg_move.max_radius) / 100.0f);
|
||||
m_ps_move_tracker->set_filter_small_contours(m_filter_small_contours);
|
||||
m_ps_move_tracker->set_show_all_contours(m_show_all_contours);
|
||||
m_ps_move_tracker->set_draw_contours(m_draw_contours);
|
||||
|
|
Loading…
Add table
Reference in a new issue