mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
Merge branch 4.x
This commit is contained in:
@@ -27,7 +27,8 @@ void yoloPostProcessing(
|
||||
std::vector<Rect2d>& keep_boxes,
|
||||
float conf_threshold,
|
||||
float iou_threshold,
|
||||
const std::string& test_name
|
||||
const std::string& model_name,
|
||||
const int nc
|
||||
);
|
||||
|
||||
std::vector<std::string> classes;
|
||||
@@ -40,6 +41,7 @@ std::string keys =
|
||||
"{ yolo | yolox | yolo model version. }"
|
||||
"{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera. }"
|
||||
"{ classes | | Optional path to a text file with names of classes to label detected objects. }"
|
||||
"{ nc | 80 | Number of classes. Default is 80 (coming from COCO dataset). }"
|
||||
"{ thr | .5 | Confidence threshold. }"
|
||||
"{ nms | .4 | Non-maximum suppression threshold. }"
|
||||
"{ mean | 0.0 | Normalization constant. }"
|
||||
@@ -107,19 +109,21 @@ void yoloPostProcessing(
|
||||
std::vector<Rect2d>& keep_boxes,
|
||||
float conf_threshold,
|
||||
float iou_threshold,
|
||||
const std::string& test_name)
|
||||
const std::string& model_name,
|
||||
const int nc=80)
|
||||
{
|
||||
// Retrieve
|
||||
std::vector<int> classIds;
|
||||
std::vector<float> confidences;
|
||||
std::vector<Rect2d> boxes;
|
||||
|
||||
if (test_name == "yolov8")
|
||||
if (model_name == "yolov8" || model_name == "yolov10" ||
|
||||
model_name == "yolov9")
|
||||
{
|
||||
cv::transposeND(outs[0], {0, 2, 1}, outs[0]);
|
||||
}
|
||||
|
||||
if (test_name == "yolonas")
|
||||
if (model_name == "yolonas")
|
||||
{
|
||||
// outs contains 2 elemets of shape [1, 8400, 80] and [1, 8400, 4]. Concat them to get [1, 8400, 84]
|
||||
Mat concat_out;
|
||||
@@ -131,25 +135,30 @@ void yoloPostProcessing(
|
||||
// remove the second element
|
||||
outs.pop_back();
|
||||
// unsqueeze the first dimension
|
||||
outs[0] = outs[0].reshape(0, std::vector<int>{1, 8400, 84});
|
||||
outs[0] = outs[0].reshape(0, std::vector<int>{1, 8400, nc + 4});
|
||||
}
|
||||
|
||||
// assert if last dim is 85 or 84
|
||||
CV_CheckEQ(outs[0].dims, 3, "Invalid output shape. The shape should be [1, #anchors, 85 or 84]");
|
||||
CV_CheckEQ((outs[0].size[2] == nc + 5 || outs[0].size[2] == 80 + 4), true, "Invalid output shape: ");
|
||||
|
||||
for (auto preds : outs)
|
||||
{
|
||||
preds = preds.reshape(1, preds.size[1]); // [1, 8400, 85] -> [8400, 85]
|
||||
for (int i = 0; i < preds.rows; ++i)
|
||||
{
|
||||
// filter out non object
|
||||
float obj_conf = (test_name == "yolov8" || test_name == "yolonas") ? 1.0f : preds.at<float>(i, 4) ;
|
||||
float obj_conf = (model_name == "yolov8" || model_name == "yolonas" ||
|
||||
model_name == "yolov9" || model_name == "yolov10") ? 1.0f : preds.at<float>(i, 4) ;
|
||||
if (obj_conf < conf_threshold)
|
||||
continue;
|
||||
|
||||
Mat scores = preds.row(i).colRange((test_name == "yolov8" || test_name == "yolonas") ? 4 : 5, preds.cols);
|
||||
Mat scores = preds.row(i).colRange((model_name == "yolov8" || model_name == "yolonas" || model_name == "yolov9" || model_name == "yolov10") ? 4 : 5, preds.cols);
|
||||
double conf;
|
||||
Point maxLoc;
|
||||
minMaxLoc(scores, 0, &conf, 0, &maxLoc);
|
||||
|
||||
conf = (test_name == "yolov8" || test_name == "yolonas") ? conf : conf * obj_conf;
|
||||
conf = (model_name == "yolov8" || model_name == "yolonas" || model_name == "yolov9" || model_name == "yolov10") ? conf : conf * obj_conf;
|
||||
if (conf < conf_threshold)
|
||||
continue;
|
||||
|
||||
@@ -161,7 +170,7 @@ void yoloPostProcessing(
|
||||
double h = det[3];
|
||||
|
||||
// [x1, y1, x2, y2]
|
||||
if (test_name == "yolonas"){
|
||||
if (model_name == "yolonas" || model_name == "yolov10"){
|
||||
boxes.push_back(Rect2d(cx, cy, w, h));
|
||||
} else {
|
||||
boxes.push_back(Rect2d(cx - 0.5 * w, cy - 0.5 * h,
|
||||
@@ -203,6 +212,7 @@ int main(int argc, char** argv)
|
||||
// if model is default, use findFile to get the full path otherwise use the given path
|
||||
std::string weightPath = findFile(parser.get<String>("model"));
|
||||
std::string yolo_model = parser.get<String>("yolo");
|
||||
int nc = parser.get<int>("nc");
|
||||
|
||||
float confThreshold = parser.get<float>("thr");
|
||||
float nmsThreshold = parser.get<float>("nms");
|
||||
@@ -219,6 +229,7 @@ int main(int argc, char** argv)
|
||||
// check if yolo model is valid
|
||||
if (yolo_model != "yolov5" && yolo_model != "yolov6"
|
||||
&& yolo_model != "yolov7" && yolo_model != "yolov8"
|
||||
&& yolo_model != "yolov10" && yolo_model !="yolov9"
|
||||
&& yolo_model != "yolox" && yolo_model != "yolonas")
|
||||
CV_Error(Error::StsError, "Invalid yolo model: " + yolo_model);
|
||||
|
||||
@@ -331,7 +342,8 @@ int main(int argc, char** argv)
|
||||
yoloPostProcessing(
|
||||
outs, keep_classIds, keep_confidences, keep_boxes,
|
||||
confThreshold, nmsThreshold,
|
||||
yolo_model);
|
||||
yolo_model,
|
||||
nc);
|
||||
//![postprocess]
|
||||
|
||||
// covert Rect2d to Rect
|
||||
|
||||
@@ -6,6 +6,9 @@ if(UNIX)
|
||||
find_package(X11 QUIET)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(EPOXY QUIET epoxy)
|
||||
|
||||
SET(OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS
|
||||
opencv_core
|
||||
opencv_imgproc
|
||||
@@ -22,6 +25,9 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
if(NOT X11_FOUND)
|
||||
ocv_list_filterout(all_samples "opengl_interop")
|
||||
endif()
|
||||
if(NOT EPOXY_FOUND)
|
||||
ocv_list_filterout(all_samples "opengl3_2")
|
||||
endif()
|
||||
foreach(sample_filename ${all_samples})
|
||||
ocv_define_sample(tgt ${sample_filename} opengl)
|
||||
ocv_target_link_libraries(${tgt} PRIVATE "${OPENGL_LIBRARIES}" "${OPENCV_OPENGL_SAMPLES_REQUIRED_DEPS}")
|
||||
@@ -29,6 +35,10 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
ocv_target_link_libraries(${tgt} PRIVATE ${X11_LIBRARIES})
|
||||
ocv_target_include_directories(${tgt} ${X11_INCLUDE_DIR})
|
||||
endif()
|
||||
if(sample_filename STREQUAL "opengl3_2.cpp")
|
||||
ocv_target_link_libraries(${tgt} PRIVATE ${EPOXY_LIBRARIES})
|
||||
ocv_target_include_directories(${tgt} PRIVATE ${EPOXY_INCLUDE_DIRS})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#define NOMINMAX 1
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/core/opengl.hpp"
|
||||
#include "opencv2/core/cuda.hpp"
|
||||
#include "opencv2/highgui.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::cuda;
|
||||
|
||||
const int win_width = 800;
|
||||
const int win_height = 640;
|
||||
|
||||
struct DrawData
|
||||
{
|
||||
GLuint vao, vbo, program, textureID;
|
||||
};
|
||||
|
||||
static cv::Mat rot(float angle)
|
||||
{
|
||||
cv::Mat R_y = (cv::Mat_<float>(4,4) <<
|
||||
cos(angle), 0, sin(angle), 0,
|
||||
0, 1, 0, 0,
|
||||
-sin(angle), 0, cos(angle), 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
return R_y;
|
||||
}
|
||||
|
||||
static GLuint create_shader(const char* source, GLenum type) {
|
||||
GLuint shader = glCreateShader(type);
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
static void draw(void* userdata) {
|
||||
DrawData* data = static_cast<DrawData*>(userdata);
|
||||
static float angle = 0.0f;
|
||||
angle += 1.f;
|
||||
|
||||
cv::Mat trans = rot(CV_PI * angle / 360.f);
|
||||
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glUseProgram(data->program);
|
||||
glUniformMatrix4fv(glGetUniformLocation(data->program, "transform"), 1, GL_FALSE, trans.ptr<float>());
|
||||
glBindTexture(GL_TEXTURE_2D, data->textureID);
|
||||
glBindVertexArray(data->vao);
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
string filename;
|
||||
if (argc < 2)
|
||||
{
|
||||
cout << "Usage: " << argv[0] << " image" << endl;
|
||||
filename = "baboon.jpg";
|
||||
}
|
||||
else
|
||||
filename = argv[1];
|
||||
|
||||
Mat img = imread(samples::findFile(filename));
|
||||
if (img.empty())
|
||||
{
|
||||
cerr << "Can't open image " << filename << endl;
|
||||
return -1;
|
||||
}
|
||||
flip(img, img, 0);
|
||||
|
||||
namedWindow("OpenGL", WINDOW_OPENGL);
|
||||
resizeWindow("OpenGL", win_width, win_height);
|
||||
|
||||
DrawData data;
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
const char *vertex_shader_source =
|
||||
"#version 330 core\n"
|
||||
"layout (location = 0) in vec3 position;\n"
|
||||
"layout (location = 1) in vec2 texCoord;\n"
|
||||
"out vec2 TexCoord;\n"
|
||||
"uniform mat4 transform;\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = transform * vec4(position, 1.0);\n"
|
||||
" TexCoord = texCoord;\n"
|
||||
"}\n";
|
||||
const char *fragment_shader_source =
|
||||
"#version 330 core\n"
|
||||
"in vec2 TexCoord;\n"
|
||||
"out vec4 color;\n"
|
||||
"uniform sampler2D ourTexture;\n"
|
||||
"void main() {\n"
|
||||
" color = texture(ourTexture, TexCoord);\n"
|
||||
"}\n";
|
||||
data.program = glCreateProgram();
|
||||
GLuint vertex_shader = create_shader(vertex_shader_source, GL_VERTEX_SHADER);
|
||||
GLuint fragment_shader = create_shader(fragment_shader_source, GL_FRAGMENT_SHADER);
|
||||
glAttachShader(data.program, vertex_shader);
|
||||
glAttachShader(data.program, fragment_shader);
|
||||
glLinkProgram(data.program);
|
||||
glUseProgram(data.program);
|
||||
|
||||
GLfloat vertices[] = {
|
||||
// Positions // Texture Coords
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top Left
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f // Bottom Left
|
||||
};
|
||||
|
||||
glGenVertexArrays(1, &data.vao);
|
||||
glGenBuffers(1, &data.vbo);
|
||||
glBindVertexArray(data.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Position attribute
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
// Texture Coord attribute
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindVertexArray(0); // Unbind VAO
|
||||
|
||||
|
||||
// Image to texture
|
||||
glGenTextures(1, &data.textureID);
|
||||
glBindTexture(GL_TEXTURE_2D, data.textureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.cols, img.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, img.data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
setOpenGlDrawCallback("OpenGL", draw, &data);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
updateWindow("OpenGL");
|
||||
char key = (char)waitKey(40);
|
||||
if (key == 27)
|
||||
break;
|
||||
}
|
||||
|
||||
setOpenGlDrawCallback("OpenGL", 0, 0);
|
||||
destroyAllWindows();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user