小项目01:尿试纸条没有放到位问题检测

目录

  • 一、完整代码
    • 1.1 返回值含义
    • 1.2 main
    • 1.3 bvdetector.h
    • 1.4 bvdetector.cpp
  • 二、图例
    • 1. 原图scrImg
    • 2.灰度图img_gray
    • 3.二值图binImg
    • 4.反二值图invImg

一、完整代码

1.1 返回值含义

0:表示正常(有角度);1:表示没有图片;2,表示有多条交叉图片;3,表示反面;4,表示正面反向;5:正面倾作严重,6:无效的长宽比(检验的纸条类型与当前设置纸条的类型不一致,7:表示没有点样;

1.2 main

//#include "dryDetector.h"
#include "bvdetector.h"#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;int main(int argc, char* argv[]) {//    QString imagePath="D:/aaa/1.jpg";
//    Mat outputMat;
//    int resultID;
//    double tiltAngle;
//    int whiltBlockL_R;//    bool result=getStripFromOpencv(imagePath,outputMat,resultID,tiltAngle,whiltBlockL_R);
//    cout << "resultID: " <<resultID << endl;
//    cout << "tiltAngle: " <<tiltAngle << endl;
//    cout << "whiltBlockL_R: " <<whiltBlockL_R << endl;
//    cout << "result: " <<result << endl;//    imshow("outputMat",outputMat);
//    waitKey(0);
//    return 0;//    QString imagePath="E:/workCode/QTProjects/dryDetect/aaa/13.jpg";//    Mat outputMat;
//    int resultID;
//    double tiltAngle;
//    int whiltBlockL_R;//    bool result=getBvFromOpencv(imagePath,outputMat,resultID,tiltAngle,whiltBlockL_R);
//    if (result){//        Mat SourceImage;//        cvtColor(outputMat, SourceImage, COLOR_BGR2GRAY);//        Mat img;
//        medianBlur(SourceImage, img, 7);//        vector<Vec3f> cir;
//        HoughCircles(img, cir, CV_HOUGH_GRADIENT, 1, 19, 130, 20,  1, 12);//        for (size_t i = 0; i < cir.size(); i++) {
//                circle(outputMat, Point(cir[i][0], cir[i][1]), cir[i][2], Scalar(0, 255, 0), 1);
//                circle(outputMat, Point(cir[i][0], cir[i][1]), 1, Scalar(0, 0, 255), 1);
//        }//        imshow("outputMat",outputMat);
//        waitKey(0);
//    }/* InputArray image, OutputArray circles,int method, double dp, double minDist,double param1 = 100, double param2 = 100,int minRadius = 0, int maxRadius = 0*/QString imagePath="E:/workCode/Learn_CUDA/OPENCV_TRANDITION/4/strip1_loadImage.jpg";processStripImgOkFlag(imagePath);return 0;
}

1.3 bvdetector.h

#pragma once
#include <opencv2/opencv.hpp>
#include<time.h>
#include <math.h>
#include <QString>int  detect(cv::String imagePath,int isDebug);
bool getBvFromOpencv(QString& imgPath, cv::Mat &outputMat, int& resultID, double& tiltAngle, int& whiltBlockL_R);
bool processStripImgOkFlag(QString& imgPath);

1.4 bvdetector.cpp

#include "bvdetector.h"using namespace std;
using namespace cv;#define PI acos(-1);
//params
int moreAreaThreshold=120000;
int backAreaThreshold=60000;
int emptyAreaThreshold=20000;
int hisThresholdY=15000;
int hisThresholdX=5000;const  int URINE_WHITE_LEFT = 1;
const  int URINE_WHITE_RIGHT = 2;const  int URINE_NORMAL = 0;
const  int URINE_EMPTY = 1;
const  int URINE_MORE = 2;
const  int URINE_BACK = 3;
const  int URINE_FRONT_LEFT = 4;
const  int ADJUST_PIXEL =0;Mat rotateImg(Mat src,double angle ){Mat rot_mat( 2, 3, CV_32FC1 );Mat rotated_src;Point center = Point( src.cols/2, src.rows/2 );rot_mat = getRotationMatrix2D( center, angle, 1 );warpAffine( src, rotated_src, rot_mat, src.size() );return rotated_src;
}int judgeMore(Mat binImg){Scalar areas = sum(binImg);double area=areas[0]/255;//    cout << "area:"<<area << endl;if(area>=moreAreaThreshold){return 2;//more}else if(area<emptyAreaThreshold){return 1;//empty}else{return 0;//normal}
}double calAngle(Mat edges){vector<Vec4i> lines;double urineThea=0;HoughLinesP( edges, lines, 1, CV_PI/720, 10, 300, 50);if(lines.size()>0){double x1=lines[0][0];double y1=lines[0][1];double x2=lines[0][2];double y2=lines[0][3];if(x2!=x1){urineThea=-atan((y2 - y1) / (x2 - x1));urineThea= urineThea * 180 / PI;}}return urineThea;
}Mat getPatch(int& resultID, int& whiltBlockL_R,Mat image,Mat edges){Mat fullIamge = image.clone();//1.get init patchint topPoint = 0;int bottomPoint = 0;int leftPoint = 0;int rightPoint = 0;Mat histogramY(image.rows, 1, CV_32SC4, Scalar(0));reduce(edges, histogramY, 1, CV_REDUCE_SUM,CV_32SC4);
//    int topPix=0;
//    int bottompix=0;for (int i = 0; i < image.rows; i++){int tempPix=histogramY.at<int>(i, 0);if (topPoint == 0 && tempPix > hisThresholdY){topPoint = i;
//            topPix=tempPix;}else if(tempPix > hisThresholdY ){bottomPoint = i;
//              bottompix=tempPix;}}
//    int leftPix=0;
//    int rightpix=0;Mat histogramX(1, image.cols, CV_32SC4, Scalar(0));reduce(edges.rowRange(topPoint,bottomPoint), histogramX, 0, CV_REDUCE_SUM,CV_32SC4);for (int j = 0; j < image.cols; j++){int tempPix=histogramX.at<int>(0, j);if (leftPoint == 0 && tempPix > hisThresholdX){leftPoint = j;
//            leftPix=tempPix;}else if(tempPix > hisThresholdX ){rightPoint = j;
//            rightpix=tempPix;}}return  fullIamge.colRange(leftPoint+ADJUST_PIXEL,rightPoint-ADJUST_PIXEL).rowRange(topPoint+ADJUST_PIXEL,bottomPoint-ADJUST_PIXEL);}bool getBvFromOpencv(QString& imgPath, cv::Mat &outputMat, int& resultID, double& tiltAngle, int& labelL_R){clock_t start, end;start = clock();bool result=true;if(imgPath==nullptr){result=false;cout << "imgPath is error"  << endl;return result;}Mat scrImg= imread(imgPath.toStdString().c_str(),IMREAD_COLOR);if(scrImg.empty()){result=false;cout << "imgPath is error"  << endl;return result;}//    3. handle img gray->blur->bin->cannyMat gray,blurImg,binImg,edgesImg;cvtColor(scrImg, gray, COLOR_BGR2GRAY);GaussianBlur(gray,blurImg,Size(3, 3), 0);threshold(blurImg,binImg,0, 255,THRESH_BINARY + THRESH_OTSU);Canny(binImg, edgesImg, 50, 150);//    4. judgeMoreint state=judgeMore(binImg);// 5.calc angle and rotateswitch (state) {case 2:resultID=URINE_MORE;result=false;//        cout << "more than single strip."  << endl;break;case 1:resultID=URINE_EMPTY;result=false;//        cout << "contain empty strip."  << endl;break;default:resultID=URINE_NORMAL;//        cout << "single strip."  << endl;double angle=calAngle(edgesImg);//        cout << "angle:"<< angle << endl;if (angle*angle<0.3){angle=0;}else{scrImg = rotateImg(scrImg, -angle);
//            edgesImg= rotateImg(edgesImg, -angle);}tiltAngle=angle;if(tiltAngle>=50){result=false;}cvtColor(scrImg, gray, COLOR_BGR2GRAY);GaussianBlur(gray,blurImg,Size(3, 3), 0);threshold(blurImg,binImg,0, 255,THRESH_BINARY + THRESH_OTSU);Canny(binImg, edgesImg, 50, 150);//        6.handle rotated image and extract  patchif(result)outputMat=getPatch(resultID,labelL_R,scrImg, edgesImg);if(labelL_R==1){result=false;}}end = clock();cout << "Searching time: " << difftime(end, start) / CLOCKS_PER_SEC << endl;return result;
}void getPatch(Mat image,Mat edges){Mat fullIamge = image.clone();//1.get init patchint topPoint = 0;int bottomPoint = 0;int leftPoint = 0;int rightPoint = 0;Mat histogramY(image.rows, 1, CV_32SC4, Scalar(0));reduce(edges, histogramY, 1, CV_REDUCE_SUM,CV_32SC4);for (int i = 0; i < image.rows; i++){int tempPix=histogramY.at<int>(i, 0);//        cout<<histogramY.at<int>(i, 0)<<endl;if (topPoint == 0 && tempPix > hisThresholdY){topPoint = i;}else if(tempPix > hisThresholdY ){bottomPoint = i;}}Mat histogramX(1, image.cols, CV_32SC4, Scalar(0));reduce(edges.rowRange(topPoint,bottomPoint), histogramX, 0, CV_REDUCE_SUM,CV_32SC4);for (int j = 0; j < image.cols; j++){int tempPix=histogramX.at<int>(0, j);//        cout<<tempPix<<endl;if (leftPoint == 0 && tempPix > hisThresholdX){leftPoint = j;}else if(tempPix > hisThresholdX ){rightPoint = j;}}//2.correct patchMat gray,blurImg,binImg;cvtColor(fullIamge.colRange(leftPoint,rightPoint).rowRange(topPoint,bottomPoint), gray, COLOR_BGR2GRAY);GaussianBlur(gray,blurImg,Size(3, 3), 0);threshold(blurImg,binImg,0, 1,THRESH_BINARY + THRESH_OTSU);int leftx_base = sum(binImg.colRange(0,int(binImg.cols/2)))[0];int rightx_base = sum(binImg.colRange(int(binImg.cols/2),binImg.cols))[0];if (rightx_base>leftx_base){//        cout << "leftBlack"  << endl;if(rightPoint- leftPoint > 970){int leftSpace=leftPoint+50;int tempLeftPoint=0;Mat temphistogramX=histogramX.colRange(leftSpace,image.cols);//            Mat temphistogramX(1, image.cols-leftSpace, CV_32SC4, Scalar(0));//            reduce(correctEdges.colRange(leftSpace,image.cols), temphistogramX, 0, CV_REDUCE_SUM,CV_32SC4);//            imshow("correctEdges",correctEdges.colRange(leftSpace,image.cols));for (int i = 0; i <temphistogramX.cols; i++){int tempPix=temphistogramX.at<int>(0, i);if (tempLeftPoint == 0 && tempPix > hisThresholdX){tempLeftPoint = i;break;}}leftPoint=tempLeftPoint+leftSpace;}}else{//        cout << "rightBlack"  << endl;if(rightPoint- leftPoint > 970){int temprightPoint=rightPoint-50;Mat temphistogramX=histogramX.colRange(0,temprightPoint);for (int i = 0; i < temphistogramX.cols; i++){int tempPix=temphistogramX.at<int>(0, i);if ( tempPix > hisThresholdX){temprightPoint = i;}}rightPoint=temprightPoint;}}//    imshow("cropend",fullIamge.colRange(leftPoint,rightPoint).rowRange(topPoint,bottomPoint));
}int  detect(String imagePath,int isDebug = 1) {clock_t start, end;start = clock();Mat scrImg= imread(imagePath,IMREAD_COLOR);//    3. handle img gray->blur->bin->cannyMat gray,blurImg,binImg,edgesImg;cvtColor(scrImg, gray, COLOR_BGR2GRAY);GaussianBlur(gray,blurImg,Size(3, 3), 0);threshold(blurImg,binImg,0, 255,THRESH_BINARY + THRESH_OTSU);Canny(blurImg, edgesImg, 50, 150);//    4. judgeMoreint state=judgeMore(binImg);// 5.calc angle and rotateswitch (state) {case 3:cout << "more than single strip."  << endl;break;case 2:cout << "contain back strip."  << endl;break;case 1:cout << "contain empty strip."  << endl;break;default:cout << "single strip."  << endl;double angle=calAngle(edgesImg);cout << "angle:"<< angle << endl;if (angle*angle<0.3){angle=0;}else{scrImg = rotateImg(scrImg, -angle);edgesImg= rotateImg(edgesImg, -angle);}//        6.handle rotated image and extract  patch//        getPatch(scrImg, edgesImg);}end = clock();cout << "Searching time: " << difftime(end, start) / CLOCKS_PER_SEC << endl;waitKey(0);return 1;
}bool processStripImgOkFlag(QString& imgPath){clock_t start, end;start = clock();bool result=true;int thresh_length=45;if(imgPath==nullptr){result=false;cout << "imgPath is error"  << endl;return result;}Mat scrImg= imread(imgPath.toStdString().c_str(),IMREAD_COLOR);if(scrImg.empty()){result=false;cout << "imgPath is error"  << endl;return result;}//cv2.threshold(img_gray, 40, 255, cv2.THRESH_BINARY)//    3. handle img gray->blur->bin->cannyvector<vector<Point>> contours;vector<Vec4i> hierarchy;Mat img_gray,binImg,invImg;cvtColor(scrImg, img_gray, COLOR_BGR2GRAY);imwrite("d:/img_gray.jpg",img_gray);threshold(img_gray,binImg,40, 255,THRESH_BINARY);threshold(img_gray,invImg,40, 255,THRESH_BINARY_INV);imwrite("d:/binImg.jpg",binImg);imwrite("d:/invImg.jpg",invImg);findContours(binImg,contours,hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point());int max_area=0,max_id=0;//1.计算最大凸包for (int i =0;i<contours.size();i++) {int temp=contourArea(contours[i]);if(temp>max_area){max_area=temp;max_id=i;}}int left=scrImg.cols,right=0;int offset=20;//2.计算最大凸包的左右坐标for (int i =0;i<contours[max_id].size();i++) {Point tempPoint=contours[max_id][i];if(tempPoint.x<left){left=tempPoint.x;}if(tempPoint.x>right){right=tempPoint.x;}}left+=offset;right-=offset;Mat histogramX(1,right-left+1, CV_32SC4, Scalar(0));reduce(invImg.colRange(left,right+1), histogramX, 0, CV_REDUCE_SUM,CV_32SC4);//3.统计未被试纸条覆盖的空白区域长度int blank_length=0;for (int j = 0; j < histogramX.cols; j++){int tempPix=histogramX.at<int>(0, j);
//               cout<<j<<":"<<tempPix<<endl;if (tempPix>0)blank_length++;}//4.长度大于一个色块判断没完全覆盖if (blank_length>thresh_length){result=false;}cout<<result<<" blank_length:"<<blank_length<<endl;end = clock();cout << "Searching time: " << difftime(end, start) / CLOCKS_PER_SEC << endl;return result;
}

二、图例

1. 原图scrImg

在这里插入图片描述

2.灰度图img_gray

在这里插入图片描述

3.二值图binImg

在这里插入图片描述

4.反二值图invImg

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/50234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言实现:从RSA PEM文件中提取私钥n/e/d/p/q/dp/dq/qp因子

我们知道使用openssl命令行openssl rsa -in test_priv.pem -text 即可实现从私钥PEM文件中提取私钥因子&#xff1a;n/e/d/p/q/dp/dq/qp. 那么如何用C语言实现呢&#xff1f;如何在代码中实现呢&#xff1f; #include <stdio.h> #include <stdlib.h> #include &l…

el-button实现按钮,鼠标移入显示,移出隐藏

2023.8.18今天我学习了 如何实现鼠标移入显示按钮&#xff0c;鼠标移出隐藏按钮。 效果如图&#xff1a; 鼠标移入时&#xff1a; 鼠标移出时&#xff1a; mouseover //鼠标移入事件 mouseleave //鼠标移出事件 原本我是想直接在el-button写入这两个方法&#xff0c;但是elem…

Nuxt3环境变量配置

Nuxt3 正式发布还不到半年&#xff0c;在投入生产环境使用后&#xff0c;遇到了不少问题&#xff0c;很难找到合适的解决方案&#xff0c;其中环境变量配置就是其中一个&#xff0c;之前一直未能解决&#xff0c;最近要上持续集成&#xff0c;无法绕过这个问题&#xff0c;所以…

工厂方法模式介绍

韩敬海 设计模式&#xff08;Java版&#xff09; &#xff08;一&#xff09;定义 定义一个创建对象的接口&#xff0c;让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。 工厂方法涉及的角色有&#xff1a; 1 .抽象工厂角色&#xff1a;工厂方法模式的核心&am…

clion软件ide的安装和环境配置@ubuntu

1.官网&#xff1a; Download CLion 2.安装Clion 直接在官网下载并安装即可&#xff0c;过程很简单 https://www.jetbrains.com/clion/ https://www.jetbrains.com/clion/download/#sectionlinux 3.激活码 4.配置Clion 安装gcc、g、make Ubuntu中用到的编译工具是gcc©…

Redis 列表 | Navicat

在最近的博客 文章 中&#xff0c;我们已经了解了 Redis 的六种数据类型。其中&#xff0c;Redis 列表&#xff08;List&#xff09;包含一组字符串&#xff0c;他们按照被添加的顺序进行排序。本文将就列表数据类型进行展开介绍&#xff0c;并且重点介绍一些主要的命令来管理它…

RPC和HTTP协议

RPC 全称&#xff08;Remote Procedure Call&#xff09;&#xff0c;它是一种针对跨进程或者跨网络节点的应用之间的远程过程调用协议。 它的核心目标是&#xff0c;让开发人员在进行远程方法调用的时候&#xff0c;就像调用本地方法一样&#xff0c;不需要额外为了完成这个交…

MyBatis动态SQL、模糊查询与结果映射

目录 前言 一、MyBatis动态SQL 1.动态SQL是什么 2.动态SQL的作用 3.常用动态SQL元素 1. where if 元素 2. set if 元素 3. choose when otherwise 元素 4. 自定义 trim 元素 <1>. 自定义 trim 元素改写上面的 where if 语句 <2>. 自定义 trim 元素改…

将AI融入CG特效工作流;对谈Dify创始人张路宇;关于Llama 2的一切资源;普林斯顿LLM高阶课程;LLM当前的10大挑战 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 将AI融入CG特效工作流&#xff0c;体验极致的效率提升 BV1pP411r7HY 这是 B站UP主 特效小哥studio 和 拓星研究所 联合投稿的一个AI特…

SpringBoot 调用外部接口

SpringBoot 调用外部接口 一、第一种方式(HttpClient等) 使用插件方式&#xff0c;比如自带的HttpClient&#xff0c;或者OkHttp&#xff0c;甚至是原生的HttpURLConnection 等等&#xff0c;这里以HttpClient为例。 1、封装工具类 简单封装的get请求 /*** 发送get请求:带请求…

纹波和噪声测试知识

随着开关频率和开关速度不断的提升&#xff0c;在使用开关型的DC/DC电源的时候&#xff0c;要特别关注输入输出电源的纹波。但是测量DC/DC电源的纹波和噪声没有一个行业标准。不同厂家的测试环境以及测试标准都不太一样&#xff0c;导致很多人很迷惑。这篇文章提供了一个简单可…

go rpc

运用go标准库写一个rpc例子 服务端 package mainimport ("fmt""net""net/rpc" )//对象 type Hello struct { } //对象方法 func (h *Hello) HelloWorld(name string, resp *string) error {*resp name "你好"return nil }func mai…

赋能道路交通场景,九州未来助力建成广西交科车路协同智能网联示范园区

智慧高速车路协同需要更加稳固的技术基座 智慧高速是中国高速公路建设的热点之一&#xff0c;车路协同又是未来智慧高速建设的核心内容。高速公路运行环境相对简单、主体权责清晰、路侧机电设施齐全&#xff0c;具备开展车路协同创新示范的良好条件。 广西交科集团&#xff0…

编程锦囊妙计——快速创建本地Mock服务

点击上方&#x1f446;蓝色“Agilean”&#xff0c;发现更多精彩。 前情提要 在本系列上一篇文章《全文干货&#xff1a;打破前后端数据传递鸿沟&#xff0c;高效联调秘笈》中我们分享了使用Zod这一运行时类型校验库来对后端服务响应结果进行验证达到增加项目质量的方式。 这次…

三维重建_体素重建_空间雕刻法/体素着色法

目录 1. 三角化和体素重建的区别 2. 空间雕刻法 空间雕刻法的一致性定义 空间雕刻法具体实现 基于八叉树的空间雕刻法具体实现​编辑 空间雕刻法效果展示 3. 体素着色法 体素着色法的缺点&#xff1a;不唯一性​编辑 体素着色法不唯一性解决措施​编辑 体素着色发实验环境与…

Ansible 自动化安装软件

例子如下&#xff1a; 创建一个名为/ansible/package.yml 的 playbook : 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上 将 RPM Development Tools 软件包组安装到 dev 主机组中的主机上 将 dev 主机组中主机上的所有软件包更新为最新版本 --- - name:…

Linux系统安全:NAT(SNAT、DNAT)

目录 一.NAT 二.SNAT 三.DNAT 一.NAT NAT: network address translation&#xff0c;支持PREROUTING&#xff0c;INPUT&#xff0c;OUTPUT&#xff0c;POSTROUTING四个链 请求报文&#xff1a;修改源/目标IP&#xff0c; 响应报文&#xff1a;修改源/目标IP&#xff0c;根据…

单片机的串口通信

今天&#xff0c;完整地总结一下普中科技的单片机的串口通信的硬件与编程&#xff0c;记录一下以后如果需要也比较方便捡起来。 单片机的串口部分的电路图。开发板上集成了 1 个串口通信电路&#xff0c;是 USB 转串口模块&#xff0c;它既可下载程序也可实现串口通信功能。 对…

WEB APIs day5

一、window对象 BOM属于window对象 1.BOM&#xff08;浏览器对象模型&#xff09; bom里面包含着dom,只不过bom我们平时用得比较少&#xff0c;我们经常使用的是dom操作&#xff0c;因为我们页面中的这些标签都是在dom中取的&#xff0c;所以我们操作dom多一点。 window对象…

neo4j

UNWIND 将列表里的值展开 CREATE (N0:Person {name: Anders}) CREATE (N1:Person {name: Becky}) CREATE (N2:Person {name: Cesar}) CREATE (N3:Person {name: Dilshad}) CREATE (N4:Person {name: George}) CREATE (N5:Person {name: Filipa})CREATE (N0)-[:KNOWS]->(N3)…