diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/Camera.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/Camera.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a76786bdf71a5edf341171ae8fafaa4b9ac45b3c --- /dev/null +++ b/NahidaProject.ThirdParty/Sources/OpenCV/Camera.cpp @@ -0,0 +1,248 @@ +#include "Camera.h" + +// 打开摄像头(通过索引) +bool NahidaProject::ThirdParty::Camera::Open(int cameraIndex) { + return cap.open(cameraIndex); +} + +// 打开视频文件 +bool NahidaProject::ThirdParty::Camera::Open(const std::string& filename) { + return cap.open(filename); +} + +// 关闭摄像头 +void NahidaProject::ThirdParty::Camera::Close() { + Stop(); + if (cap.isOpened()) { + cap.release(); + } +} + +// 检查摄像头是否打开 +bool NahidaProject::ThirdParty::Camera::IsOpened() const { + return cap.isOpened(); +} + +// 单帧捕获 +bool NahidaProject::ThirdParty::Camera::Read(cv::Mat& image) { + return cap.read(image); +} + +// 获取当前帧 +cv::Mat NahidaProject::ThirdParty::Camera::GetFrame() { + std::lock_guard lock(frameMutex); + return frame.clone(); +} + +// 启动连续捕获线程 +void NahidaProject::ThirdParty::Camera::Start() { + if (!IsOpened() || isRunning) return; + + isRunning = true; + captureThread = std::thread(&Camera::CaptureLoop, this); +} + +// 停止连续捕获 +void NahidaProject::ThirdParty::Camera::Stop() { + isRunning = false; + if (captureThread.joinable()) { + captureThread.join(); + } +} + +// 设置摄像头属性 +bool NahidaProject::ThirdParty::Camera::SetProperty(int property, double value) { + return cap.set(property, value); +} + +// 获取摄像头属性 +double NahidaProject::ThirdParty::Camera::GetProperty(int property) const { + return cap.get(property); +} + +// 设置分辨率 +bool NahidaProject::ThirdParty::Camera::SetResolution(int width, int height) { + bool success = true; + success &= cap.set(cv::CAP_PROP_FRAME_WIDTH, width); + success &= cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); + return success; +} + +// 获取分辨率 +std::pair NahidaProject::ThirdParty::Camera::GetResolution() const { + int width = static_cast(cap.get(cv::CAP_PROP_FRAME_WIDTH)); + int height = static_cast(cap.get(cv::CAP_PROP_FRAME_HEIGHT)); + return { width, height }; +} + +// 设置帧率 +bool NahidaProject::ThirdParty::Camera::SetFPS(double fps) { + return cap.set(cv::CAP_PROP_FPS, fps); +} + +// 获取帧率 +double NahidaProject::ThirdParty::Camera::GetFPS() const { + return cap.get(cv::CAP_PROP_FPS); +} + +// 设置曝光时间 +bool NahidaProject::ThirdParty::Camera::SetExposure(double exposure) { + return cap.set(cv::CAP_PROP_EXPOSURE, exposure); +} + +// 获取曝光时间 +double NahidaProject::ThirdParty::Camera::GetExposure() const { + return cap.get(cv::CAP_PROP_EXPOSURE); +} + +// 设置亮度 +bool NahidaProject::ThirdParty::Camera::SetBrightness(double brightness) { + return cap.set(cv::CAP_PROP_BRIGHTNESS, brightness); +} + +// 获取亮度 +double NahidaProject::ThirdParty::Camera::GetBrightness() const { + return cap.get(cv::CAP_PROP_BRIGHTNESS); +} + +// 设置对比度 +bool NahidaProject::ThirdParty::Camera::SetContrast(double contrast) { + return cap.set(cv::CAP_PROP_CONTRAST, contrast); +} + +// 获取对比度 +double NahidaProject::ThirdParty::Camera::GetContrast() const { + return cap.get(cv::CAP_PROP_CONTRAST); +} + +// 设置饱和度 +bool NahidaProject::ThirdParty::Camera::SetSaturation(double saturation) { + return cap.set(cv::CAP_PROP_SATURATION, saturation); +} + +// 获取饱和度 +double NahidaProject::ThirdParty::Camera::GetSaturation() const { + return cap.get(cv::CAP_PROP_SATURATION); +} + +// 设置色相 +bool NahidaProject::ThirdParty::Camera::SetHue(double hue) { + return cap.set(cv::CAP_PROP_HUE, hue); +} + +// 获取色相 +double NahidaProject::ThirdParty::Camera::GetHue() const { + return cap.get(cv::CAP_PROP_HUE); +} + +// 设置增益 +bool NahidaProject::ThirdParty::Camera::SetGain(double gain) { + return cap.set(cv::CAP_PROP_GAIN, gain); +} + +// 获取增益 +double NahidaProject::ThirdParty::Camera::GetGain() const { + return cap.get(cv::CAP_PROP_GAIN); +} + +// 获取总帧数(对于视频文件) +double NahidaProject::ThirdParty::Camera::GetFrameCount() const { + return cap.get(cv::CAP_PROP_FRAME_COUNT); +} + +// 设置当前帧位置(对于视频文件) +bool NahidaProject::ThirdParty::Camera::SetFramePosition(double pos) { + return cap.set(cv::CAP_PROP_POS_FRAMES, pos); +} + +// 获取当前帧位置 +double NahidaProject::ThirdParty::Camera::GetFramePosition() const { + return cap.get(cv::CAP_PROP_POS_FRAMES); +} + +// 获取视频时长(秒) +double NahidaProject::ThirdParty::Camera::GetDuration() const { + return cap.get(cv::CAP_PROP_FRAME_COUNT) / cap.get(cv::CAP_PROP_FPS); +} + +// 获取当前播放位置(秒) +double NahidaProject::ThirdParty::Camera::GetCurrentTime() const { + return cap.get(cv::CAP_PROP_POS_MSEC) / 1000.0; +} + +// 设置播放位置(秒) +bool NahidaProject::ThirdParty::Camera::SetCurrentTime(double seconds) { + return cap.set(cv::CAP_PROP_POS_MSEC, seconds * 1000.0); +} + +// 截图并保存 +bool NahidaProject::ThirdParty::Camera::CaptureImage(const std::string& filename) { + cv::Mat image; + if (Read(image)) { + return cv::imwrite(filename, image); + } + return false; +} + +// 连续捕获回调函数设置 +void NahidaProject::ThirdParty::Camera::SetCaptureCallback(std::function callback) { + if (!IsRunning()) return; + + while (IsRunning()) { + cv::Mat currentFrame; + if (Read(currentFrame)) { + { + std::lock_guard lock(frameMutex); + frame = currentFrame.clone(); + } + callback(currentFrame); + } + std::this_thread::sleep_for(std::chrono::milliseconds(30)); // 约33fps + } +} + +// 检查是否正在运行 +bool NahidaProject::ThirdParty::Camera::IsRunning() const { + return isRunning && cap.isOpened(); +} + +// 获取支持的摄像头列表 +std::vector NahidaProject::ThirdParty::Camera::GetAvailableCameras() { + std::vector cameras; + for (int i = 0; i < 10; ++i) { + cv::VideoCapture tempCap(i); + if (tempCap.isOpened()) { + cameras.push_back(i); + tempCap.release(); + } + } + return cameras; +} + +// 获取摄像头信息 +std::string NahidaProject::ThirdParty::Camera::GetInformation() const { + if (!IsOpened()) return "Camera not opened"; + + std::stringstream ss; + ss << "Resolution: " << GetResolution().first << "x" << GetResolution().second << "\n"; + ss << "FPS: " << GetFPS() << "\n"; + ss << "Brightness: " << GetBrightness() << "\n"; + ss << "Contrast: " << GetContrast() << "\n"; + ss << "Saturation: " << GetSaturation() << "\n"; + ss << "Hue: " << GetHue() << "\n"; + ss << "Gain: " << GetGain() << "\n"; + ss << "Exposure: " << GetExposure() << "\n"; + + return ss.str(); +} + +void NahidaProject::ThirdParty::Camera::CaptureLoop() { + while (IsRunning()) { + cv::Mat currentFrame; + if (Read(currentFrame)) { + std::lock_guard lock(frameMutex); + frame = currentFrame.clone(); + } + std::this_thread::sleep_for(std::chrono::milliseconds(30)); + } +} diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/Camera.h b/NahidaProject.ThirdParty/Sources/OpenCV/Camera.h new file mode 100644 index 0000000000000000000000000000000000000000..d8191b77eac03721a21cc55388429ef2119886d0 --- /dev/null +++ b/NahidaProject.ThirdParty/Sources/OpenCV/Camera.h @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace NahidaProject { + namespace ThirdParty { + class Camera { + private: + cv::VideoCapture cap; + cv::Mat frame; + std::mutex frameMutex; + bool isRunning; + std::thread captureThread; + + public: + Camera() : isRunning(false) { + + } + + ~Camera() { + Stop(); + } + + bool Open(int cameraIndex = 0); + bool Open(const std::string& filename); + void Close(); + bool IsOpened() const; + bool Read(cv::Mat& image); + cv::Mat GetFrame(); + void Start(); + void Stop(); + bool SetProperty(int property, double value); + double GetProperty(int property) const; + bool SetResolution(int width, int height); + std::pair GetResolution() const; + bool SetFPS(double fps); + double GetFPS() const; + bool SetExposure(double exposure); + double GetExposure() const; + bool SetBrightness(double brightness); + double GetBrightness() const; + bool SetContrast(double contrast); + double GetContrast() const; + bool SetSaturation(double saturation); + double GetSaturation() const; + bool SetHue(double hue); + double GetHue() const; + bool SetGain(double gain); + double GetGain() const; + double GetFrameCount() const; + bool SetFramePosition(double pos); + double GetFramePosition() const; + double GetDuration() const; + double GetCurrentTime() const; + bool SetCurrentTime(double seconds); + bool CaptureImage(const std::string& filename); + void SetCaptureCallback(std::function callback); + bool IsRunning() const; + static std::vector GetAvailableCameras(); + std::string GetInformation() const; + + private: + void CaptureLoop(); + }; + } +} \ No newline at end of file diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/FaceDetectorRecognizer.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/FaceDetectorRecognizer.cpp deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/FaceDetectorRecognizer.h b/NahidaProject.ThirdParty/Sources/OpenCV/FaceDetectorRecognizer.h deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..159283f5ca901abcea608473be2a241db8724c08 --- /dev/null +++ b/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.cpp @@ -0,0 +1,190 @@ +#include "FaceRecognition.h" + +// 添加训练数据 +void NahidaProject::ThirdParty::FaceRecognition::AddTrainingData(const cv::Mat& image, const std::string& name) { + // 检测人脸 + std::vector faces = DetectFaces(image); + + if (faces.empty()) { + std::cerr << "Warning:No face" << std::endl; + return; + } + + // 使用第一个人脸区域 + cv::Mat faceRoi = image(faces[0]); + + // 预处理:调整大小并转换为灰度图 + cv::Mat processedFace; + cv::resize(faceRoi, processedFace, cv::Size(100, 100)); + if (processedFace.channels() == 3) { + cv::cvtColor(processedFace, processedFace, cv::COLOR_BGR2GRAY); + } + + // 分配标签 + int label = trainingLabels.size(); + trainingImages.push_back(processedFace); + trainingLabels.push_back(label); + labelToName[label] = name; + + isTrained = false; // 需要重新训练 +} + +// 训练模型 +bool NahidaProject::ThirdParty::FaceRecognition::Train() { + if (trainingImages.empty()) { + std::cerr << "Error: No training data!" << std::endl; + return false; + } + + try { + recognizer->train(trainingImages, trainingLabels); + isTrained = true; + return true; + } + catch (const cv::Exception& e) { + std::cerr << "Error:" << e.what() << std::endl; + return false; + } +} + +// 保存模型 +bool NahidaProject::ThirdParty::FaceRecognition::SaveModel(const std::string& filename) { + if (!isTrained) { + std::cerr << "Error: Model no train" << std::endl; + return false; + } + + try { + recognizer->save(filename); + return true; + } + catch (const cv::Exception& e) { + std::cerr << "Error:" << e.what() << std::endl; + return false; + } +} + +// 加载模型 +bool NahidaProject::ThirdParty::FaceRecognition::LoadModel(const cv::String& filename) { + try { + recognizer->load(filename); + isTrained = true; + return true; + } + catch (const cv::Exception& e) { + std::cerr << "Error:" << e.what() << std::endl; + return false; + } +} + +// 人脸检测 +std::vector NahidaProject::ThirdParty::FaceRecognition::DetectFaces(const cv::Mat& image) { + std::vector faces; + + if (image.empty()) { + std::cerr << "Error: No image" << std::endl; + return faces; + } + + cv::Mat grayImage; + if (image.channels() == 3) { + cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY); + } + else { + grayImage = image.clone(); + } + + // 直方图均衡化以提高检测效果 + cv::equalizeHist(grayImage, grayImage); + + // 检测人脸 + faceCascade.detectMultiScale(grayImage, faces, 1.1, 5, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30)); + + return faces; +} + +std::vector NahidaProject::ThirdParty::FaceRecognition::Recognize(const cv::Mat& image) { + std::vector results; + + if (!isTrained) { + std::cerr << "Error: Model no train" << std::endl; + return results; + } + + if (image.empty()) { + std::cerr << "Error: No image" << std::endl; + return results; + } + + // 检测人脸 + std::vector faces = DetectFaces(image); + + for (const auto& faceRect : faces) { + // 提取人脸区域 + cv::Mat faceRoi = image(faceRect); + + // 预处理 + cv::Mat processedFace; + cv::resize(faceRoi, processedFace, cv::Size(100, 100)); + if (processedFace.channels() == 3) { + cv::cvtColor(processedFace, processedFace, cv::COLOR_BGR2GRAY); + } + + // 预测 + int predictedLabel = -1; + double confidence = 0.0; + recognizer->predict(processedFace, predictedLabel, confidence); + + // 获取人名 + std::string name = "Unknown"; + if (predictedLabel >= 0 && labelToName.find(predictedLabel) != labelToName.end()) { + name = labelToName[predictedLabel]; + } + + // 根据置信度判断是否为未知人脸(阈值可调整) + if (confidence > 80.0) { // LBPH的置信度阈值 + name = "Unknown"; + } + + results.emplace_back(name, confidence, faceRect); + } + + return results; +} + +// 在图像上绘制识别结果 +cv::Mat NahidaProject::ThirdParty::FaceRecognition::DrawResults(const cv::Mat& image, const std::vector& results) { + cv::Mat resultImage = image.clone(); + + for (const auto& result : results) { + cv::rectangle(resultImage, result.faceRect, cv::Scalar(0, 255, 0), 2); + std::string text = result.name + " (" + std::to_string(static_cast(result.confidence)) + ")"; + cv::Point text_org(result.faceRect.x, result.faceRect.y - 10); + + // 绘制背景矩形 + int baseline = 0; + cv::Size text_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.6, 2, &baseline); + cv::rectangle(resultImage, cv::Point(result.faceRect.x, result.faceRect.y - text_size.height - 10), cv::Point(result.faceRect.x + text_size.width, result.faceRect.y), cv::Scalar(0, 255, 0), -1); + cv::putText(resultImage, text, text_org, cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 255, 255), 2); + } + + return resultImage; +} + +// 获取训练状态 +bool NahidaProject::ThirdParty::FaceRecognition::IsTrained() const { + return isTrained; +} + +// 获取训练样本数量 +size_t NahidaProject::ThirdParty::FaceRecognition::GetTrainingSampleCount() const { + return trainingImages.size(); +} + +// 清除所有训练数据 +void NahidaProject::ThirdParty::FaceRecognition::ClearTrainingData() { + trainingImages.clear(); + trainingLabels.clear(); + labelToName.clear(); + isTrained = false; +} \ No newline at end of file diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.h b/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.h new file mode 100644 index 0000000000000000000000000000000000000000..2e3dc2c419614f5edcb2a4167be83a71d2d36777 --- /dev/null +++ b/NahidaProject.ThirdParty/Sources/OpenCV/FaceRecognition.h @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +namespace NahidaProject { + namespace ThirdParty { + class FaceRecognition { + private: + cv::Ptr recognizer; + cv::CascadeClassifier faceCascade; + std::vector trainingImages; + std::vector trainingLabels; + std::map labelToName; + bool isTrained; + + public: + struct RecognitionResult { + std::string name; + double confidence; + cv::Rect faceRect; + + RecognitionResult(const std::string& n = "Unknown", double c = 0.0, const cv::Rect& rect = cv::Rect()) : name(n), confidence(c), faceRect(rect) { + + } + }; + + FaceRecognition() : isTrained(false) { + recognizer = cv::face::LBPHFaceRecognizer::create(); + // 也可以使用其他算法: + // recognizer = cv::face::EigenFaceRecognizer::create(); + // recognizer = cv::face::FisherFaceRecognizer::create(); + + if (!faceCascade.load("haarcascade_frontalface_default.xml")) { + std::cerr << "错误:无法加载人脸检测模型文件!" << std::endl; + std::cerr << "请确保 haarcascade_frontalface_default.xml 文件在当前目录中" << std::endl; + } + } + + // 析构函数 + ~FaceRecognition() {} + + // 添加训练数据 + void AddTrainingData(const cv::Mat& image, const std::string& name); + bool Train(); + bool SaveModel(const std::string& filename); + bool LoadModel(const cv::String& filename); + std::vector DetectFaces(const cv::Mat& image); + + // 识别人脸 + std::vector Recognize(const cv::Mat& image); + cv::Mat DrawResults(const cv::Mat& image, const std::vector& results); + bool IsTrained() const; + size_t GetTrainingSampleCount() const; + void ClearTrainingData(); + }; + } +} \ No newline at end of file diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/ImageWatermark.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/ImageWatermark.cpp index f0265bfed5d3f7ea505fcf7d3d0aac4b9a16f46c..144ee6be76bbde684f92dfd80305718f7f58b973 100644 --- a/NahidaProject.ThirdParty/Sources/OpenCV/ImageWatermark.cpp +++ b/NahidaProject.ThirdParty/Sources/OpenCV/ImageWatermark.cpp @@ -46,7 +46,7 @@ bool NahidaProject::ThirdParty::ImageWatermark::LoadImage(const std::string& ima } // 明水印 - 添加可见水印 -cv::Mat NahidaProject::ThirdParty::ImageWatermark::AddVisibleWatermark(const std::string& text, double alpha, const cv::Point& position, int fontSize = 1, const cv::Scalar& color) { +cv::Mat NahidaProject::ThirdParty::ImageWatermark::AddVisibleWatermark(const std::string& text, double alpha, const cv::Point& position, int fontSize, const cv::Scalar& color) { if (originalImage.empty()) { std::cerr << "Error: Original image is empty" << std::endl; diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/KNNClassifier.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/KNNClassifier.cpp index 3c163cdd0a7cd401a466a33f98f069b3958a52ee..8d7dba577f36b0277aa80b3a5de02e4df2427212 100644 --- a/NahidaProject.ThirdParty/Sources/OpenCV/KNNClassifier.cpp +++ b/NahidaProject.ThirdParty/Sources/OpenCV/KNNClassifier.cpp @@ -168,7 +168,7 @@ float NahidaProject::ThirdParty::KNNClassifier::WeightedPredict(const cv::Mat& s return bestLabel; } -double NahidaProject::ThirdParty::KNNClassifier::CalculateDistance(const cv::Mat& a, const cv::Mat& b, DistanceMetric metric, double p = 3.0) { +double NahidaProject::ThirdParty::KNNClassifier::CalculateDistance(const cv::Mat& a, const cv::Mat& b, DistanceMetric metric, double p) { switch (metric) { case EUCLIDEAN: return cv::norm(a, b, cv::NORM_L2); diff --git a/NahidaProject.ThirdParty/Sources/OpenCV/PictureProcessor.cpp b/NahidaProject.ThirdParty/Sources/OpenCV/PictureProcessor.cpp index 7ae737b1d0b5f18a6601919559af1e4c079139b9..01073bb126df15683ca772ec241fd17abb36185a 100644 --- a/NahidaProject.ThirdParty/Sources/OpenCV/PictureProcessor.cpp +++ b/NahidaProject.ThirdParty/Sources/OpenCV/PictureProcessor.cpp @@ -137,7 +137,7 @@ void NahidaProject::ThirdParty::PictureProcessor::ApplyBlur(int kernelSize) { } // 高斯模糊 -void NahidaProject::ThirdParty::PictureProcessor::ApplyGaussianBlur(int kernelSize, double sigmaX = 0) { +void NahidaProject::ThirdParty::PictureProcessor::ApplyGaussianBlur(int kernelSize, double sigmaX) { cv::GaussianBlur(image, image, cv::Size(kernelSize, kernelSize), sigmaX); SaveToHistory(); } @@ -278,9 +278,9 @@ void NahidaProject::ThirdParty::PictureProcessor::AddNoise(double noiseIntensity // 添加水印 void NahidaProject::ThirdParty::PictureProcessor::AddWatermark(const std::string& watermarkText, - cv::Point position = cv::Point(50, 50), - double fontSize = 1.0, - cv::Scalar color = cv::Scalar(255, 255, 255)) { + cv::Point position, + double fontSize, + cv::Scalar color) { cv::putText(image, watermarkText, position, cv::FONT_HERSHEY_SIMPLEX, fontSize, color, 2); SaveToHistory(); }