mirror of
https://gitlab.fdmci.hva.nl/technische-informatica-sm3/ti-projectten/rooziinuubii79.git
synced 2025-08-03 11:55:00 +00:00
Grabbed existing progam off github and repaired it
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,7 +13,7 @@ src/Socket/a.out
|
||||
src/C++/Driver/cmake_install.cmake
|
||||
src/C++/Socket/a.out
|
||||
src/C++/Driver/Makefile
|
||||
src/C++/Driver/vgcore*
|
||||
vgcore*
|
||||
src/C++/Driver/cmake_install.cmake
|
||||
src/C++/Driver/Makefile
|
||||
src/C++/Driver/log
|
||||
|
@@ -1,8 +1,20 @@
|
||||
# OpenCV
|
||||
## Requirements
|
||||
For the camera we want it to detect what is happening on the video feed and identify it so it can identify dangers.
|
||||
|
||||
|
||||
## Issues
|
||||
|
||||
* OpenCL not grabbing gpu
|
||||
* Solution: https://github.com/Smorodov/Multitarget-tracker/issues/93
|
||||
|
||||
## Installation
|
||||
### Dependencies
|
||||
* glew
|
||||
* opencv
|
||||
* opencv
|
||||
|
||||
|
||||
|
||||
|
||||
## Sources
|
||||
* https://github.com/UnaNancyOwen/OpenCVDNNSample/tree/master
|
@@ -1,15 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
# Find the Paho MQTT C++ library
|
||||
find_library(PAHO_MQTTPP_LIBRARY paho-mqttpp3 PATHS /usr/local/lib)
|
||||
find_library(PAHO_MQTT_LIBRARY paho-mqtt3a PATHS /usr/local/lib)
|
||||
|
||||
# Include the headers
|
||||
include_directories(/usr/local/include)
|
||||
|
||||
# Add the executable
|
||||
add_executable(my_program main.cpp)
|
||||
|
||||
# Link the libraries
|
||||
target_link_libraries(my_program ${PAHO_MQTTPP_LIBRARY} ${PAHO_MQTT_LIBRARY})
|
@@ -1,64 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <mqtt/async_client.h>
|
||||
#include <thread> // For std::this_thread::sleep_for
|
||||
#include <chrono> // For std::chrono::seconds
|
||||
|
||||
// Define the address of the MQTT broker, the client ID, and the topic to subscribe to.
|
||||
const std::string ADDRESS("mqtt://localhost:1883"); // Broker address (Raspberry Pi)
|
||||
const std::string CLIENT_ID("raspberry_pi_client");
|
||||
const std::string TOPIC("home/commands");
|
||||
|
||||
// Define a callback class that handles incoming messages and connection events.
|
||||
class callback : public virtual mqtt::callback {
|
||||
// Called when a message arrives on a subscribed topic.
|
||||
void message_arrived(mqtt::const_message_ptr msg) override {
|
||||
std::cout << "Received message: '" << msg->get_topic()<< "' : " << msg->to_string() << std::endl;
|
||||
}
|
||||
|
||||
// Called when the connection to the broker is lost.
|
||||
void connection_lost(const std::string& cause) override {
|
||||
std::cerr << "Connection lost. Reason: " << cause << std::endl;
|
||||
}
|
||||
|
||||
// Called when a message delivery is complete.
|
||||
void delivery_complete(mqtt::delivery_token_ptr token) override {
|
||||
std::cout << "Message delivered!" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
// Create an MQTT async client and set up the callback class.
|
||||
mqtt::async_client client(ADDRESS, CLIENT_ID);
|
||||
callback cb;
|
||||
client.set_callback(cb);
|
||||
|
||||
// Set up the connection options (such as username and password).
|
||||
mqtt::connect_options connOpts;
|
||||
connOpts.set_clean_session(true);
|
||||
connOpts.set_user_name("ishak");
|
||||
connOpts.set_password("kobuki");
|
||||
connOpts.set_mqtt_version(MQTTVERSION_3_1_1);
|
||||
|
||||
try {
|
||||
// Try to connect to the broker and wait until successful.
|
||||
std::cout << "Connecting to broker..." << std::endl;
|
||||
client.connect(connOpts)->wait(); // Connect with the provided options
|
||||
std::cout << "Connected!" << std::endl;
|
||||
|
||||
// Subscribe to the specified topic and wait for confirmation.
|
||||
std::cout << "Subscribing to topic: " << TOPIC << std::endl;
|
||||
client.subscribe(TOPIC, 1)->wait(); // Subscribe with QoS level 1
|
||||
|
||||
// Keep the program running to continue receiving messages from the broker.
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1)); // Sleep to reduce CPU usage
|
||||
}
|
||||
|
||||
} catch (const mqtt::exception &exc) {
|
||||
// Catch any MQTT exceptions and display the error message.
|
||||
std::cerr << "Error: " << exc.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0; // Return 0 to indicate successful execution
|
||||
}
|
@@ -1,9 +1,44 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project( main )
|
||||
cmake_minimum_required( VERSION 3.6 )
|
||||
|
||||
# Require C++11 (or later)
|
||||
set( CMAKE_CXX_STANDARD 23 )
|
||||
set( CMAKE_CXX_STANDARD_REQUIRED ON )
|
||||
set( CMAKE_CXX_EXTENSIONS OFF )
|
||||
set(BUILD_MODE Debug)
|
||||
# Create Project
|
||||
project( Sample )
|
||||
add_executable( YOLOv4 util.h main.cpp )
|
||||
|
||||
# Set StartUp Project
|
||||
set_property( DIRECTORY PROPERTY VS_STARTUP_PROJECT "YOLOv4" )
|
||||
|
||||
# Find Package
|
||||
# OpenCV
|
||||
find_package( OpenCV REQUIRED )
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
add_executable( main main.cpp )
|
||||
target_link_libraries( main ${OpenCV_LIBS} )
|
||||
|
||||
if( OpenCV_FOUND )
|
||||
# Additional Include Directories
|
||||
include_directories( ${OpenCV_INCLUDE_DIRS} )
|
||||
|
||||
# Additional Dependencies
|
||||
target_link_libraries( YOLOv4 ${OpenCV_LIBS} )
|
||||
endif()
|
||||
|
||||
# Download Model
|
||||
set( MODEL https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v3_optimal/yolov4.weights )
|
||||
file( DOWNLOAD
|
||||
"${MODEL}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/yolov4.weights"
|
||||
EXPECTED_HASH SHA256=e8a4f6c62188738d86dc6898d82724ec0964d0eb9d2ae0f0a9d53d65d108d562
|
||||
SHOW_PROGRESS
|
||||
)
|
||||
|
||||
|
||||
#sauce: https://docs.opencv.org/4.x/db/df5/tutorial_linux_gcc_cmake.html
|
||||
# Download Config
|
||||
set( CONFIG https://raw.githubusercontent.com/AlexeyAB/darknet/master/cfg/yolov4.cfg )
|
||||
file( DOWNLOAD
|
||||
"${CONFIG}"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/yolov4.cfg"
|
||||
EXPECTED_HASH SHA256=a6d0f8e5c62cc8378384f75a8159b95fa2964d4162e33351b00ac82e0fc46a34
|
||||
SHOW_PROGRESS
|
||||
)
|
||||
|
BIN
src/C++/OpenCV/YOLOv4
Executable file
BIN
src/C++/OpenCV/YOLOv4
Executable file
Binary file not shown.
80
src/C++/OpenCV/coco.names
Normal file
80
src/C++/OpenCV/coco.names
Normal file
@@ -0,0 +1,80 @@
|
||||
person
|
||||
bicycle
|
||||
car
|
||||
motorbike
|
||||
aeroplane
|
||||
bus
|
||||
train
|
||||
truck
|
||||
boat
|
||||
traffic light
|
||||
fire hydrant
|
||||
stop sign
|
||||
parking meter
|
||||
bench
|
||||
bird
|
||||
cat
|
||||
dog
|
||||
horse
|
||||
sheep
|
||||
cow
|
||||
elephant
|
||||
bear
|
||||
zebra
|
||||
giraffe
|
||||
backpack
|
||||
umbrella
|
||||
handbag
|
||||
tie
|
||||
suitcase
|
||||
frisbee
|
||||
skis
|
||||
snowboard
|
||||
sports ball
|
||||
kite
|
||||
baseball bat
|
||||
baseball glove
|
||||
skateboard
|
||||
surfboard
|
||||
tennis racket
|
||||
bottle
|
||||
wine glass
|
||||
cup
|
||||
fork
|
||||
knife
|
||||
spoon
|
||||
bowl
|
||||
banana
|
||||
apple
|
||||
sandwich
|
||||
orange
|
||||
broccoli
|
||||
carrot
|
||||
hot dog
|
||||
pizza
|
||||
donut
|
||||
cake
|
||||
chair
|
||||
sofa
|
||||
pottedplant
|
||||
bed
|
||||
diningtable
|
||||
toilet
|
||||
tvmonitor
|
||||
laptop
|
||||
mouse
|
||||
remote
|
||||
keyboard
|
||||
cell phone
|
||||
microwave
|
||||
oven
|
||||
toaster
|
||||
sink
|
||||
refrigerator
|
||||
book
|
||||
clock
|
||||
vase
|
||||
scissors
|
||||
teddy bear
|
||||
hair drier
|
||||
toothbrush
|
@@ -1,31 +1,209 @@
|
||||
#include <opencv4/opencv2/core/core.hpp>
|
||||
#include <opencv4/opencv2/imgcodecs.hpp>
|
||||
#include <opencv4/opencv2/highgui/highgui.hpp>
|
||||
#include "opencv4/opencv2/imgproc/imgproc.hpp"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
#include "util.h"
|
||||
|
||||
// Helper function to check if a file exists
|
||||
bool fileExists(const std::string &path)
|
||||
{
|
||||
return std::filesystem::exists(path);
|
||||
}
|
||||
|
||||
int main() {
|
||||
Mat myImage; //Declaring a matrix to load the frames
|
||||
namedWindow("Video Player"); //Declaring the video to show the video//
|
||||
VideoCapture cap(0); //Declaring an object to capture stream of frames from default camera//
|
||||
if (!cap.isOpened()){ //This section prompt an error message if no video stream is found//
|
||||
cout << "No video stream detected" << endl;
|
||||
system("pause");
|
||||
return-1;
|
||||
}
|
||||
while (true){
|
||||
cap >> myImage; //
|
||||
if (myImage.empty()){ //Breaking the loop if no video frame is detected//
|
||||
break;
|
||||
}
|
||||
imshow("Video Player", myImage); //Showing the video//
|
||||
char c = (char)waitKey(25); //Allowing 25 milliseconds frame processing time and initiating break condition//
|
||||
}
|
||||
cap.release(); //Releasing the buffer memory//
|
||||
return 0;
|
||||
}
|
||||
// Function to read class names from a file
|
||||
std::vector<std::string> _readClassNameList(const std::string &path)
|
||||
{
|
||||
std::vector<std::string> classes;
|
||||
|
||||
// Check if file exists
|
||||
if (!fileExists(path))
|
||||
{
|
||||
throw std::runtime_error("Class names file not found: " + path);
|
||||
}
|
||||
|
||||
// Try to open and read file
|
||||
std::ifstream file(path);
|
||||
if (!file.is_open())
|
||||
{
|
||||
throw std::runtime_error("Unable to open class names file: " + path);
|
||||
}
|
||||
|
||||
std::string line;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (!line.empty())
|
||||
{
|
||||
classes.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (classes.empty())
|
||||
{
|
||||
throw std::runtime_error("No classes found in file: " + path);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
// Open Video Capture
|
||||
cv::VideoCapture capture = cv::VideoCapture(0);
|
||||
if (!capture.isOpened())
|
||||
{
|
||||
std::cerr << "Failed to open camera device" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read Class Name List and Color Table
|
||||
const std::string list = "coco.names";
|
||||
const std::vector<std::string> classes = _readClassNameList(list);
|
||||
const std::vector<cv::Scalar> colors = getClassColors(classes.size());
|
||||
|
||||
// Debug: Print the size of the colors vector
|
||||
std::cout << "Number of colors: " << colors.size() << std::endl;
|
||||
|
||||
// Read Darknet
|
||||
const std::string model = "yolov4.weights";
|
||||
const std::string config = "yolov4.cfg";
|
||||
cv::dnn::Net net = cv::dnn::readNet(model, config);
|
||||
if (net.empty())
|
||||
{
|
||||
std::cerr << "Failed to load network" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set Preferable Backend
|
||||
net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);
|
||||
|
||||
// Set Preferable Target
|
||||
net.setPreferableTarget(cv::dnn::DNN_TARGET_OPENCL);
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Read Frame
|
||||
cv::Mat frame;
|
||||
capture >> frame;
|
||||
if (frame.empty())
|
||||
{
|
||||
cv::waitKey(0);
|
||||
break;
|
||||
}
|
||||
if (frame.channels() == 4)
|
||||
{
|
||||
cv::cvtColor(frame, frame, cv::COLOR_BGRA2BGR);
|
||||
}
|
||||
|
||||
// Create Blob from Input Image
|
||||
cv::Mat blob = cv::dnn::blobFromImage(frame, 1 / 255.f, cv::Size(416, 416), cv::Scalar(), true, false);
|
||||
|
||||
// Set Input Blob
|
||||
net.setInput(blob);
|
||||
|
||||
// Run Forward Network
|
||||
std::vector<cv::Mat> detections;
|
||||
net.forward(detections, getOutputsNames(net));
|
||||
|
||||
// Draw Region
|
||||
std::vector<int32_t> class_ids;
|
||||
std::vector<float> confidences;
|
||||
std::vector<cv::Rect> rectangles;
|
||||
for (cv::Mat &detection : detections)
|
||||
{
|
||||
if (detection.empty())
|
||||
{
|
||||
std::cerr << "Detection matrix is empty!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
for (int32_t i = 0; i < detection.rows; i++)
|
||||
{
|
||||
cv::Mat region = detection.row(i);
|
||||
|
||||
// Retrieve Max Confidence and Class Index
|
||||
cv::Mat scores = region.colRange(5, detection.cols);
|
||||
cv::Point class_id;
|
||||
double confidence;
|
||||
cv::minMaxLoc(scores, 0, &confidence, 0, &class_id);
|
||||
|
||||
// Check Confidence
|
||||
constexpr float threshold = 0.2;
|
||||
if (threshold > confidence)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve Object Position
|
||||
const int32_t x_center = static_cast<int32_t>(region.at<float>(0) * frame.cols);
|
||||
const int32_t y_center = static_cast<int32_t>(region.at<float>(1) * frame.rows);
|
||||
const int32_t width = static_cast<int32_t>(region.at<float>(2) * frame.cols);
|
||||
const int32_t height = static_cast<int32_t>(region.at<float>(3) * frame.rows);
|
||||
const cv::Rect rectangle = cv::Rect(x_center - (width / 2), y_center - (height / 2), width, height);
|
||||
|
||||
// Add Class ID, Confidence, Rectangle
|
||||
class_ids.push_back(class_id.x);
|
||||
confidences.push_back(confidence);
|
||||
rectangles.push_back(rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove Overlap Rectangles using Non-Maximum Suppression
|
||||
constexpr float confidence_threshold = 0.5; // Confidence
|
||||
constexpr float nms_threshold = 0.5; // IoU (Intersection over Union)
|
||||
std::vector<int32_t> indices;
|
||||
cv::dnn::NMSBoxes(rectangles, confidences, confidence_threshold, nms_threshold, indices);
|
||||
|
||||
// Draw Rectangle
|
||||
for (const int32_t &index : indices)
|
||||
{
|
||||
// Bounds checking
|
||||
if (class_ids[index] >= colors.size())
|
||||
{
|
||||
std::cerr << "Color index out of bounds: " << class_ids[index] << " (max: " << colors.size() - 1 << ")" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
const cv::Rect rectangle = rectangles[index];
|
||||
const cv::Scalar color = colors[class_ids[index]];
|
||||
|
||||
// Debug: Print the index and color
|
||||
std::cout << "Drawing rectangle with color index: " << class_ids[index] << std::endl;
|
||||
|
||||
constexpr int32_t thickness = 3;
|
||||
cv::rectangle(frame, rectangle, color, thickness);
|
||||
|
||||
std::string label = classes[class_ids[index]] + ": " + std::to_string(static_cast<int>(confidences[index] * 100)) + "%";
|
||||
|
||||
int baseLine;
|
||||
cv::Size labelSize = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
|
||||
int top = std::max(rectangle.y, labelSize.height);
|
||||
cv::rectangle(frame, cv::Point(rectangle.x, top - labelSize.height),
|
||||
cv::Point(rectangle.x + labelSize.width, top + baseLine), color, cv::FILLED);
|
||||
cv::putText(frame, label, cv::Point(rectangle.x, top), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 255, 255), 1);
|
||||
}
|
||||
|
||||
// Show Image
|
||||
cv::imshow("Object Detection", frame);
|
||||
const int32_t key = cv::waitKey(1);
|
||||
if (key == 'q')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cv::destroyAllWindows();
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// cloned and fixed from https://github.com/UnaNancyOwen/OpenCVDNNSample/tree/master
|
61
src/C++/OpenCV/util.h
Normal file
61
src/C++/OpenCV/util.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef __UTIL__
|
||||
#define __UTIL__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
|
||||
// Get Output Layers Name
|
||||
std::vector<std::string> getOutputsNames( const cv::dnn::Net& net )
|
||||
{
|
||||
static std::vector<std::string> names;
|
||||
if( names.empty() ){
|
||||
std::vector<int32_t> out_layers = net.getUnconnectedOutLayers();
|
||||
std::vector<std::string> layers_names = net.getLayerNames();
|
||||
names.resize( out_layers.size() );
|
||||
for( size_t i = 0; i < out_layers.size(); ++i ){
|
||||
names[i] = layers_names[out_layers[i] - 1];
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// Get Output Layer Type
|
||||
std::string getOutputLayerType( cv::dnn::Net& net )
|
||||
{
|
||||
const std::vector<int32_t> out_layers = net.getUnconnectedOutLayers();
|
||||
const std::string output_layer_type = net.getLayer( out_layers[0] )->type;
|
||||
return output_layer_type;
|
||||
}
|
||||
|
||||
// Read Class Name List
|
||||
std::vector<std::string> readClassNameList( const std::string list_path )
|
||||
{
|
||||
std::vector<std::string> classes;
|
||||
std::ifstream ifs( list_path );
|
||||
if( !ifs.is_open() ){
|
||||
return classes;
|
||||
}
|
||||
std::string class_name = "";
|
||||
while( std::getline( ifs, class_name ) ){
|
||||
classes.push_back( class_name );
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
// Get Class Color Table for Visualize
|
||||
std::vector<cv::Scalar> getClassColors( const int32_t number_of_colors )
|
||||
{
|
||||
cv::RNG random;
|
||||
std::vector<cv::Scalar> colors;
|
||||
for( int32_t i = 0; i < number_of_colors; i++ ){
|
||||
cv::Scalar color( random.uniform( 0, 255 ), random.uniform( 0, 255 ), random.uniform( 0, 255 ) );
|
||||
colors.push_back( color );
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
#endif // __UTIL__
|
1158
src/C++/OpenCV/yolov4.cfg
Normal file
1158
src/C++/OpenCV/yolov4.cfg
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/C++/OpenCV/yolov4.weights
Normal file
BIN
src/C++/OpenCV/yolov4.weights
Normal file
Binary file not shown.
Reference in New Issue
Block a user