不多废话,直接上代码:
#include "read.hpp"
#include <math.h>#include <algorithm>//圆形PCB板,有led灯点亮时
int DetectImage::native_read_pic(cv::String path){if(access(path.c_str(),F_OK)!=0){f << "Open pic file failed!" << std::endl;return -1;}f << "native_read_ " << std::endl;cv::namedWindow("camera", cv::WINDOW_AUTOSIZE);cv::Mat img = cv::imread(path);cv::Mat resize_img(img);cv::resize(img, resize_img, cv::ls/cameraInfo.scale, ws/cameraInfo.scale));//缩小大小cv::Mat draw_img(resize_img);//拷贝一张,便于画出轮廓cv::cvtColor(resize_img,resize_img,cv::COLOR_BGR2GRAY);//变成灰度cv::GaussianBlur(resize_img,resize_img,cv::Size(11,11),0);//高斯变化cv:threshold(resize_img,resize_img,cameraInfo.threshold_value, cameraInfo.maxval,cv::THRESH_BINARY);//二值化std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;cv::findContours(resize_img,contours,hierarchy,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);std::cout << contours.size() << std::endl;//计算面积contourAreastd::vector<double> Area_all;for (int i = 0; i < contours.size(); i++){Area_all.push_back(cv::contourArea(contours[i]));}double sum = std::accumulate(std::begin(Area_all), std::end(Area_all), 0.0); double mean = sum / Area_all.size(); //周长的均值std::vector<double>::iterator biggest = std::max_element(Area_all.begin(), d());int find_index = -1;if(*biggest > mean *5){//如果最大值>平均值*5的话find_index = std::distance(Area_all.begin(), biggest);char text_show[16]={0};sprintf(text_show,"Numis:%d",find_index);cv::putText(draw_img, text_show, cv::Point(20, 20), cv::FONT_HERSHEY_SIMPLEX, 0.9, cv::Scalar(255, 0, 0));}for (int i = 0; i < contours.size(); i++){if(i != find_index){cv::drawContours(draw_img,contours,i,cv::Scalar(0, 0, 255), 1,8,hierarchy);}}cv::imshow("camera", draw_img);cv::waitKey(0); return contours.size();
}// camera open
int DetectImage::camera_operationImage(unsigned char read_or_wirte,const char* path){ //>> 1920×1080 == 1080p//打开一个默认的相机cv::VideoCapture capture(cameraInfo.camera_id);//检查是否成功打开if (!capture.isOpened()){f << "Open capture failed!" << cameraInfo.camera_id << std::endl;return -1;}//设置摄像头的分辨率capture.set(cv::CAP_PROP_FRAME_WIDTH, cameraInfo.width);capture.set(cv::CAP_PROP_FRAME_HEIGHT, cameraInfo.height);capture.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));//摄像头帧数capture.set(cv::CAP_PROP_FPS, cameraInfo.fps);static unsigned char save_number = 1;while(1){cv::Mat frame;capture>>frame;if(read_or_wirte == 0){cv::imshow("camera",frame);}if(save_number && read_or_wirte){if(path == NULL || strlen(path) == 0){cv::imwrite(cameraInfo.save_pic_path,frame);}else{cv::imwrite(path,frame);}save_number--;cv::imshow("camera",frame);}if(cv::waitKey(30)==27){break;}if(save_number==0){break;}}return 0;
}
//读配置文件
int DetectImage::readjson(std::string json_path){Json::Reader json_reader;Json::Value json_value;std::ifstream infile(json_path, std::ios::binary);if(!infile.is_open()){f << "Open config file failed!" << std::endl;return -1;}if(json_reader.parse(infile, json_value)){std::string pic_path = json_value["SavePath"].asString();std::string log_path = json_value["LogFile"].asString();//...cameraInfo.save_pic_path = pic_path;cameraInfo.logs_path = log_path;cameraInfo.camera_id = json_value["camera_id"].asInt(); // 读取字符串型参数cameraInfo.threshold_value = json_value["threshold"].asInt();cameraInfo.maxval = json_value["maxval"].asInt();cameraInfo.width = json_value["width"].asInt();cameraInfo.height = json_value["height"].asInt();cameraInfo.fps = json_value["fps"].asInt();cameraInfo.scale = json_value["scale"].asInt();//addcameraInfo.circles.is_find_circles = json_value["circles"]["is_find_circles"].asBool();cameraInfo.circles.is_draw_circles_dist = json_value["circles"]["is_draw_circles_dist"].asBool();cameraInfo.circles.minCircles_minRadius = json_value["circles"]["minCircles_minRadius"].asInt();cameraInfo.circles.minCircles_maxRadius = json_value["circles"]["minCircles_maxRadius"].asInt();cameraInfo.circles.maxCircles_minRadius = json_value["circles"]["maxCircles_minRadius"].asInt();cameraInfo.circles.maxCircles_maxRadius = json_value["circles"]["maxCircles_maxRadius"].asInt();//d_color_hmin = json_value["colors"]["red_color_hmin"].asInt();d_color_hmax = json_value["colors"]["red_color_hmax"].asInt();_color_hmin = json_value["colors"]["green_color_hmin"].asInt();_color_hmax = json_value["colors"]["green_color_hmax"].asInt();lors.blue_color_hmin = json_value["colors"]["blue_color_hmin"].asInt();lors.blue_color_hmax = json_value["colors"]["blue_color_hmax"].asInt();lor_smin = json_value["colors"]["color_smin"].asInt();lor_smax = json_value["colors"]["color_smax"].asInt();}else{init_default_camera();}infile.close();return 0;
}
//设置默认参数
void DetectImage::init_default_camera(){//set default settingscameraInfo.camera_id = 0;cameraInfo.scale = 1;cameraInfo.threshold_value = 209;cameraInfo.maxval = 255;cameraInfo.width = 640;cameraInfo.height = 480;cameraInfo.fps = 60;cameraInfo.logs_path = "./";cameraInfo.save_pic_path = "./Detect_image.jpeg";//addcameraInfo.circles = {false,false,5,15,100,120};lors = {0,10,35,77,100,124,43,255};f << "use default_camera_params !" << std::endl;
}int DetectImage::process(int argc, char* argv[]){std::ofstream file_writer(cameraInfo.logs_path, std::ios_base::out);//追加写入,在原来基础上加了ios::app f.open(cameraInfo.logs_path,std::ios::out|std::ios::app);//输入你想写入的内容 if(argc < 2){f << "One argument expected"<< std::endl;f.close();return 0;}if(argc > 5){f << "Too many arguments not supplied"<< std::endl;f.close();return 0;}int ret = 0;if(strcmp(argv[1],"preview") == 0){f << ""<< std::endl;camera_operationImage(0,NULL);}else if(strcmp(argv[1],"save") == 0){camera_operationImage(1,argv[2]);f << "save "<< std::endl;}else if(strcmp(argv[1],"detect") == 0){f << ""<< std::endl;int read_ret = 0;if(argc >= 2){if(argc >= 4){if(strlen(argv[3]) > 0){if(strcmp(argv[3],"circles") == 0){ret = find_circles(argv[2]);}else if(strcmp(argv[3],"colors") == 0){ret = find_colors(argv[2],argv[4]);}return ret;}}if(strlen(argv[2]) > 0){f << "use cmd params "<< std::endl;read_ret = native_read_pic(argv[2]);}else{f << "use config file "<< std::endl;read_ret = native_read_pic(cameraInfo.save_pic_path);}}char ret_str[32]={0};sprintf(ret_str,"detect_completed:%d",read_ret);f << ret_str << std::endl;}f << "normal exit"<< std::endl;f.close();return 0;
}
//得到2点之间的距离
float DetectImage::getDistance(cv::Point pointO, cv::Point pointA)
{float distance;distance = powf((pointO.x - pointA.x), 2) + powf((pointO.y - pointA.y), 2);distance = sqrtf(distance);return distance;
}//找圆
int DetectImage::find_circles(cv::String path){cv::namedWindow("find_circles", cv::WINDOW_AUTOSIZE);if(access(path.c_str(),F_OK)!=0){f << "Open pic file failed!" << std::endl;return -1;}f << "find_ " << std::endl;if(!cameraInfo.circles.is_find_circles){f << "not find_ " << std::endl;return -2;}cv::Mat img = cv::imread(path);cv::Mat resize_img(img);cv::resize(img, resize_img, cv::ls/cameraInfo.scale, ws/cameraInfo.scale));//缩小大小cv::Mat draw_img(resize_img);cv::cvtColor(resize_img,resize_img,cv::COLOR_BGR2GRAY);//变成灰度//cv:threshold(resize_img,resize_img,cameraInfo.threshold_value, cameraInfo.maxval,cv::THRESH_BINARY);//二值化cv::medianBlur(resize_img,resize_img,3);//找小圆std::vector<cv::Vec3f> circles;cv::HoughCircles(resize_img,circles,cv::HOUGH_GRADIENT,1,10,100,30,cameraInfo.circles.minCircles_minRadius,cameraInfo.circles.minCircles_maxRadius);//should add config params f << "circles_size :" << circles.size() << std::endl;//找大圆std::vector<cv::Vec3f> Maxcircles;cv::HoughCircles(resize_img,Maxcircles,cv::HOUGH_GRADIENT,1,10,100,30,cameraInfo.circles.maxCircles_minRadius,cameraInfo.circles.maxCircles_maxRadius);//should add config params2f << "Maxcircles_size :" << Maxcircles.size() << std::endl;std::vector<double> max_dist_circle;for (size_t i = 0; i < circles.size(); i++){/* code */cv::Vec3f circle = circles[i];cv::circle(draw_img,cv::Point(circle[0],circle[1]),circle[2],cv::Scalar(0,255,0));//小圆cv::circle(draw_img,cv::Point(circle[0],circle[1]),2,cv::Scalar(0,0,255));//小圆圆心}//如果找到的大圆数量大于2个,画出⚪if(Maxcircles.size() > 2){cv::Vec3f circle = Maxcircles[0];cv::circle(draw_img,cv::Point(circle[0],circle[1]),circle[2],cv::Scalar(19,69,139));//cv::circle(draw_img,cv::Point(circle[0],circle[1]),2,cv::Scalar(0,0,255));}max_dist_circle.push_back(0.0f);for (size_t i = 1; i < circles.size(); i++){cv::Vec3f o_circle = circles[0];//起始圆心cv::Vec3f circle = circles[i];//其他圆心double dist = getDistance(cv::Point(o_circle[0],o_circle[1]),cv::Point(circle[0],circle[1]));max_dist_circle.push_back(dist);//std::cout << dist << std::endl;}int max_pos = std::max_element(max_dist_circle.begin(), max_d())- max_dist_circle.begin();f << "max pos:" << max_pos << std::endl;//check range max_pos : 1 ~ size(max_dist_circle) if(circles.size() > max_pos){cv::Vec3f circles_LineA = circles[0];cv::Vec3f circles_LineB = circles[max_pos];//是否画出小圆间的 最大距离 直线if(cameraInfo.circles.is_draw_circles_dist){cv::line(draw_img,cv::Point(circles_LineA[0],circles_LineA[1]),cv::Point(circles_LineB[0],circles_LineB[1]),cv::Scalar(34,34,178));}}cv::imshow("find_circles", draw_img);cv::waitKey(0); return 0;
}/*** @brief detectHSColor 提取图像中具有特定颜色范围的区域,图像是3 通道 BGR 图像* @param image 输入图像,要求是 3 通道 BGR 图像* @param minHue Hue 的最小值,Hue 范围 0-179 (Hue本质是个角度,在0-360之间,OpenCV 用 0-180 表示。0表示红色。)* @param maxHue Hue 的最大值,Hue 范围 0-179* @param minSat Sat 的最小值,Sat 范围 0-255* @param maxSat Sat 的最大值,Sat 范围 0-255* @param mask 提取出的区域*/
void detectHSColor(const cv::Mat &image,double minHue, double maxHue,double minSat, double maxSat,cv::Mat &mask)
{cv::Mat hsv;cv::cvtColor(image, hsv, cv::COLOR_BGR2HSV);std::vector<cv::Mat> channels;cv::split(hsv, channels);cv::Mat mask1, mask2, hueMask;cv::threshold(channels[0], mask1, maxHue, 255, cv::THRESH_BINARY_INV);cv::threshold(channels[0], mask2, minHue, 255, cv::THRESH_BINARY);if(minHue < maxHue){hueMask = mask1 & mask2;}else{hueMask = mask1 | mask2;}cv::Mat satMask;cv::inRange(channels[1], minSat, maxSat, satMask);mask = hueMask & satMask;
}//找颜色
int DetectImage::find_colors(cv::String path,char* argv){cv::namedWindow("find_colors", cv::WINDOW_AUTOSIZE);if(access(path.c_str(),F_OK)!=0){f << "Open pic file failed!" << std::endl;return -1;}if(argv == NULL) {f << "plase input colors type!" << std::endl;return -2;}f << "find_colors: " << argv << " , " << std::endl;cv::Mat img = cv::imread(path);cv::Mat resize_img(img);if(cameraInfo.scale != 1){cv::resize(img, resize_img, cv::ls/cameraInfo.scale, ws/cameraInfo.scale));//缩小大小}cv::Mat draw_img(resize_img);unsigned char h_min = 0;unsigned char h_max = 0;unsigned char s_min = lor_smin;unsigned char s_max = lor_smax;if(strcmp(argv,"red") == 0){h_min = d_color_hmin;h_max = d_color_hmax;}else if(strcmp(argv,"green") == 0){h_min = _color_hmin;h_max = _color_hmax;}else if(strcmp(argv,"blue") == 0){h_min = lors.blue_color_hmin;h_max = lors.blue_color_hmax;}else{return 0;}detectHSColor(resize_img,h_min,h_max,s_min,s_max,resize_img);//找轮廓std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;cv::findContours(resize_img,contours,hierarchy,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);f << "find_colors_contours.size:" << contours.size() << std::endl;//计算面积contourAreastd::vector<double> Area_all;for (int i = 0; i < contours.size(); i++){Area_all.push_back(cv::contourArea(contours[i]));}double sum = std::accumulate(std::begin(Area_all), std::end(Area_all), 0.0); double mean = sum / Area_all.size(); //面积的均值f << "find_colors_area,mean:" << mean << std::endl;cv::imshow("find_colors", resize_img);cv::waitKey(0);return 0;
}
下面是main.cpp 的 部分:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <unistd.h>
#include <thread>
#include <string.h>
#include "read.hpp"int main(int argc, char* argv[])
{DetectImage adjson("./Config.json");detectImage.process(argc,argv);return 0;
}
下面是 头文件
#ifndef __READ_HPP
#define __READ_HPP#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <unistd.h>
#include <numeric>
#include "json/json.h"
#include <fstream>
#include <fstream>
#include <read.hpp>
#include <thread>
#include <string.h>typedef struct _Circles{bool is_find_circles;bool is_draw_circles_dist;unsigned int minCircles_minRadius;unsigned int minCircles_maxRadius;unsigned int maxCircles_minRadius;unsigned int maxCircles_maxRadius;
}Circles;typedef struct _RGBColors{unsigned char red_color_hmin;unsigned char red_color_hmax;unsigned char green_color_hmin;unsigned char green_color_hmax;unsigned char blue_color_hmin;unsigned char blue_color_hmax;unsigned char color_smin;unsigned char color_smax;
}RGBColors;typedef struct _CameraInfo {unsigned char fps;unsigned char camera_id;unsigned int threshold_value;unsigned int maxval;unsigned int width;unsigned int height;unsigned int scale;Circles circles;RGBColors colors;std::string save_pic_path;std::string logs_path;
}CameraInfo;class DetectImage
{std::fstream f;CameraInfo cameraInfo;int camera_operationImage(unsigned char read_or_wirte,const char* path);void init_default_camera();int native_read_pic(cv::String path);
public:int readjson(std::string json_path);int process(int argc, char* argv[]);//addint find_circles(cv::String path);int find_colors(cv::String path,char* argv);float getDistance(cv::Point pointO, cv::Point pointA);//两点之间距离
};
#endif
附录 上 json配置文件内容:
{"camera_id":0,"scale" :1,"threshold":200,"maxval" :255,"width" :640,"height" :480,"fps" :60,"SavePath":"./Detect_image.jpeg","LogFile":"./","circles" :{"is_find_circles":true,"is_draw_circles_dist":false,"minCircles_minRadius":25,"minCircles_maxRadius":45,"maxCircles_minRadius":300,"maxCircles_maxRadius":560},"colors" :{"red_color_hmin":0,"red_color_hmax":10,"green_color_hmin":35,"green_color_hmax":77,"blue_color_hmin":100,"blue_color_hmax":124,"color_smin":43,"color_smax":255}
}
jsoncpp 的部分需自行加载进来。谢谢~
本文发布于:2024-01-28 03:32:48,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063839744481.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |