/***************************************************************************** * *
* @brief 火焰识别
* @email 13505927373@qq.com
* @version 1.0.0.1(版本号)
* @date 2018.10.6
* 概述:此代码用于识别图片中火焰,整体思路为通过对图像的颜色处理找出图中感兴趣区域(可能为火焰的区域)及其
* 轮廓, 再提取轮廓的几何特征判断是否为火焰
* 优点:在绝大多数场景下都能较为准确恰当的提取感性兴趣区域的轮廓.
* 缺点:处理时间较慢,平均时间0.1~0.3s,个别图片1s. 对于轮廓几何特征判断做的不够完善有待提升.
* &&&提取感兴趣区域及其轮廓:
* (1)由资料得知火焰像素满足以下关系:(R > redThre &&R >= G && G>= B && S >((255 - R) * saturationTh / redThre),详细见函数findfire,由此函数实现寻找感兴趣像素点.
* (2)将图片转化为灰度图,直接转化为灰度图将损失大量信息.所以通过以下方式在保留有用信息同时将图片转化为灰度图:
* 借助第一部获得的感兴趣像素点,并求出感兴趣像素点三个通道的均值 rgb[0],rgb[1],rgb[2]
* 原图象任一点像素(B,G,R)的灰度值k表达式为 k=int(sqrt((R-rgb[0])*(R-rgb[0])+(G-rgb[1])*(G-rgb[1])+(B-rgb[2])*(B-rgb[2])))
* 详细见函数firethreold,由此生成的灰度图既能较好地保留火焰信息,以进行进一步操作
* (3) 对firethreold生成的灰度图依据灰度值进行颜色聚类,使用kmeans算法,聚类数量取3(处理过的灰度图聚类速度较快,且绝大多数情况下有较好的聚类效果).详细见函数kmean_color.
* (4) 对聚类后的各个区域用随机颜色填充,方便后续处理,详细见函数drawcc.
* (5)得到的感兴趣像素点和聚类区域分布,得到最终的感兴趣区域,详细见函数sort_po.
* &&&提取感兴趣区域轮廓的几何特征并判断是否为火焰:
* 通过感兴趣区域轮廓的不规则度,形态比例,边缘层次,直线角度判断是否为火焰,详细见函数judgefire.目前此部分有待完善,可后续加入尖角判定.
* @PS:主函数注释部分 为用meanshift进行颜色区域聚类.此算法聚类效果较好,不过基于三通道图像聚类,耗时过长,详细见函数 ShiftFiltering.
* @参考资料:
* &https://docs.opencv.org/3.4/index.html
* &https://blog.csdn.net/coldplayplay/article/details/70212483
* &https://blog.csdn.net/qq_23968185/article/details/51804574
*
*****************************************************************************/
#include <iostream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <math.h>
#include <time.h>
const int po_cout=4;
using namespace std;
using namespace cv;
Mat find_fire(Mat &inImg ,int rgb[4],int redThre=49,int saturationTh=7);//寻找感兴趣像素点
Mat ShiftFiltering(Mat img1);//实现opencv meanshift聚类算法.
Mat firethreold(Mat inImg,int* rgb);//欧式距离 灰度图
Rect min_Rect(Mat data);//返回一群点的最小外接矩形
void sort_po(Mat src,Mat res, vector <Mat> &out );//根据感兴趣像素点和聚类后的区域分布提取感兴趣区域
void kmean_color(Mat pic ,Mat &src,int color_Counts);//kmean聚类算法
void drawcc(Mat &res);//对聚类后的图片填充
int judgefire(Mat fire);//判断轮廓是否为火焰
int bSums(Mat src);//求白色像素的数量
int main() {
clock_t start,finish;
double totaltime;
start=clock();
Mat data,binary;//位置分类之后的矩阵数组
Mat original_src=imread("../f0.jpeg");
imshow("原图",original_src);
Mat src=original_src.clone();
int rgb[4]={0,0,0,0};
Mat fireimg=find_fire(src,rgb);
imshow("感兴趣点",fireimg);
//缩小查找范围
Rect rect1;
rect1=min_Rect(fireimg);
rect1.x=rect1.x-0.1*rect1.width>0 ? rect1.x-0.1*rect1.width:rect1.x ;
rect1.y=rect1.y-0.1*rect1.height>0 ? rect1.y-0.1*rect1.height:rect1.y ;
rect1.width=rect1.x+rect1.width+0.2*rect1.width<src.size[1] ? rect1.width+0.2*rect1.width:rect1.width;
rect1.height=rect1.y+rect1.height+0.2*rect1.height<src.size[0] ? rect1.height+0.2*rect1.height:rect1.height;
binary=fireimg(rect1)/255;
fireimg=firethreold(original_src,rgb);
imshow("火焰色素欧式距离灰度图",fireimg);
fireimg=fireimg(rect1);
kmean_color(fireimg,fireimg,3);
imshow("kmean聚类结果", fireimg);
// dilate(fireimg, fireimg, Mat(5, 5, CV_8UC1));
// erode(fireimg,fireimg,Mat(5, 5, CV_8UC1));
cvtColor(fireimg,fireimg,CV_GRAY2BGR);
drawcc(fireimg);
imshow("彩色填充聚类结果",fireimg);
//聚类范围与感兴趣点分布矩阵相乘
Mat colorfire=fireimg.clone();
for(int i=0;i<fireimg.rows;i++){
for(int j=0;j<fireimg.cols;j++){
if (binary.at<uchar>(i, j) == 0){
fireimg.at<Vec3b>(i, j)=Vec3b(0, 0, 0);
}
}
}
imshow("感兴趣点与聚类区域相乘法",fireimg);
vector <Mat> out;
sort_po(fireimg,colorfire,out);
RNG rng=theRNG();
//感兴趣区域轮廓判断
Mat interesting(original_src.rows, original_src.cols, CV_8UC3, Scalar(0, 0, 0));
for(int i=0;i<out.size();i++) {
Scalar newVal( rng(256), rng(256), rng(256) );
Mat original_src1=original_src.clone();
// resize(out[i], out[i], Size(rect1.width, rect1.height));
Mat tmp_bin(original_src1.rows, original_src1.cols, CV_8UC3, Scalar(0, 0, 0));
Mat maskrect = tmp_bin(rect1);
out[i].copyTo(maskrect);
int dilation_size = 1;
Mat element = getStructuringElement(MORPH_ELLIPSE,
Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));
dilate(tmp_bin, tmp_bin, element);
original_src1.setTo(0, ~tmp_bin);
cvtColor(tmp_bin,tmp_bin,CV_BGR2GRAY);
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(tmp_bin, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE );
if(judgefire(original_src1)==1){
for( size_t i1 = 0; i1< contours.size(); i1++ ) {
drawContours(original_src, contours, (int) i1, Scalar(0, 0, 255), 3, LINE_8, hierarchy, 0);
drawContours(interesting, contours, (int) i1, newVal, 2, LINE_8, hierarchy, 0);
cout<<"\n火焰!!!"<<endl;
}
} else{
for( size_t i1 = 0; i1< contours.size(); i1++ ) {
drawContours(original_src, contours, (int) i1, Scalar(0, 255, 0), 1, LINE_8, hierarchy, 0);
drawContours(interesting, contours, (int) i1, newVal, 2, LINE_8, hierarchy, 0);
}
}
}
imshow("感兴趣区域",interesting);
imshow("result(红色轮廓为火焰)",original_src);
waitKey();
finish=clock();
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
return 0;
//meanshift 颜色聚类
Rect rect1;
// rect1=min_Rect(fireimg);
// rect1.x=rect1.x-0.1*rect1.width>0 ? rect1.x-0.1*rect1.width:rect1.x ;
// rect1.y=rect1.y-0.1*rect1.height>0 ? rect1.y-0.1*rect1.height:rect1.y ;
// rect1.width=rect1.x+rect1.width+0.2*rect1.width<src.size[1] ? rect1.width+0.2*rect1.width:rect1.width;
// rect1.height=rect1.y+rect1.height+0.2*rect1.height<src.size[0] ? rect1.height+0.2*rect1.height:rect1.height;
// Mat tmp=src(rect1);
medianBlur ( tmp, tmp, 5 );
// waitKey();
// binary=fireimg(rect1)/255;
// if(tmp.cols>200&&tmp.rows>200) {
// resize(binary, binary, Size(200, binary.rows * 200 / binary.cols));
// resize(tmp, tmp, Size(200, tmp.rows * 200 / tmp.cols));
// }
// Mat res,res1;
// res1=ShiftFiltering(tmp);
// res=res1.clone();
// imshow("8",res);
// waitKey(0);
// for(int i=0;i<res.rows;i++){
// for(int j=0;j<res.cols;j++){
// if (binary.at<uchar>(i, j) == 0){
// res.at<Vec3b>(i, j)=Vec3b(0, 0, 0);
// }
// }
// }
clock_t start,finish;
double totaltime;
start=clock();
vector <Mat> out;
// sort_po(res,res1,out);
// for(int i=0;i<out.size();i++) {
// resize(out[0], out[0], Size(rect1.width, rect1.height));
// Mat tmp_bin(original_src.rows, original_src.cols, CV_8UC3, Scalar(0, 0, 0));
// Mat maskrect = tmp_bin(rect1);
// out[0].copyTo(maskrect);
// int dilation_size = 1;
// Mat element = getStructuringElement(MORPH_ELLIPSE,
// Size(2 * dilation_size + 1, 2 * dilation_size + 1),
// Point(dilation_size, dilation_size));
// dilate(tmp_bin, tmp_bin, element);
// original_src.setTo(0, ~tmp_bin);
imshow("233", original_src);
waitKey();
//
// if(judgefire(original_src)==1){
//
//
// };
//
// }
// Mat tmp=src(rect1);
rect1=min_Rect(pom[i]);
for(int i=0;i<po_cout;i++){
Rect rect1;
rect1=min_Rect(pom[i]);
Mat tmp=src(rect1);
Point point1=Point(rect1.x,rect1.y);
Point point2=Point(rect1.x+rect1.width,rect1.y+rect1.height);
rectangle(src,point1,point2, Scalar(0, 255, 255), 2, 8, 0 );
}
;
// finish=clock();
// totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
// cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
// return 0;
}
Mat find_fire(Mat &inImg ,int* rgb,int redThre,int saturationTh){
Mat fireImg;
fireImg.create(inImg.size(), CV_8UC1);
Mat multiRGB[3];
int a = inImg.channels();
split(inImg, multiRGB); //将图片拆分成R,G,B,三通道的颜色
for (int i = 0; i < inImg.rows; i++)
{
for (int j = 0; j < inImg.cols; j++)
{
float B, G, R;
B = multiRGB[0].at<uchar>(i, j); //每个像素的R,G,B值,动态地址计算法
G = multiRGB[1].at<uchar>(i, j);
R = multiRGB[2].at<uchar>(i, j);
float maxValue = max(max(B, G), R);
float minValue = min(min(B, G), R);
//与HSI中S分量的计算公式
double S = (1 - 3.0*minValue / (R + G + B));//
//R > RT R>=G>=B S>=((255-R)*ST/RT)
if (R > redThre &&R >= G && G>= B && S >((255 - R) * saturationTh / redThre))
{
fireImg.at<uchar>(i, j) = 255;
rgb[0]+=R;
rgb[1]+=G;
rgb[2]+=B;
rgb[3]+=1;
}
else
{
fireImg.at<uchar>(i, j) = 0;
}
}
}
medianBlur(fireImg, fireImg, 5);
dilate(fireImg, fireImg, Mat(5, 5, CV_8UC1));
for (int i=0;i<fireImg.rows;i++){
for(int j=0;j<fireImg.cols;j++)
{
if(fireImg.at<uchar>(i, j) ==255){
rgb[0]+=multiRGB[2].at<uchar>(i, j);;
rgb[1]+=multiRGB[1].at<uchar>(i, j);
rgb[2]+=multiRGB[0].at<uchar>(i, j);
rgb[3]+=1;
}
}
}
rgb[0]=rgb[0]/rgb[3];
rgb[1]=rgb[1]/rgb[3];
rgb[2]=rgb[2]/rgb[3];
cout<<rgb[0]<<"w"<<rgb[1]<<"w"<<rgb[2]<<"w";
return fireImg;
//erode(fireImg, fireImg, Mat(3, 3, CV_8UC1));
//GaussianBlur(fireImg, fireImg, Size(5, 5), 0, 0);
// kmean_Point(fireImg,inImg);
// DrawFire(inImg, fireImg);
// return fireImg;
}
Rect min_Rect(Mat M){
Mat data;
if (M.channels()!=1){
cvtColor(M,M,CV_BGR2GRAY);}
for(int i=0;i<M.rows;i++){
for(int j=0;j<M.cols;j++){
if ((int)M.at<uchar>(i, j)!=0){
Mat tmp = (Mat_<float>(1, 2)<< i, j);
data.push_back(tmp);
}
}
}
double minvx,maxvx;
double* minpx = &minvx;
double* maxpx = &maxvx;
double minvy,maxvy;
double* minpy = &minvy;
double* maxpy = &maxvy;
minMaxIdx(data.col(1),minpx,maxpx);
minMaxIdx(data.col(0),minpy,maxpy);
Rect g_rectangle;
g_rectangle=Rect(minvx,minvy,maxvx-minvx,maxvy-minvy);
return g_rectangle;
}
Mat ShiftFiltering(Mat img1){
clock_t start,finish;
double totaltime;
start=clock();
Mat img(img1);
// resize(img1,img,Size(150,150));
Mat res; //分割后图像
int spatialRad,colorRad;
if(img1.rows*img1.cols>40000)
{
cout<<112;
spatialRad = 50; //空间窗口大小
colorRad = 50; //色彩窗口大小}
}else{
spatialRad = 40; //空间窗口大小
colorRad = 30; }
int maxPyrLevel = 2; //金字塔层数
pyrMeanShiftFiltering( img, res, spatialRad, colorRad, maxPyrLevel); //色彩聚类平滑滤波
RNG rng = theRNG();
Mat mask( res.rows+2, res.cols+2, CV_8UC1, Scalar::all(0) ); //掩模
int n=0;
for( int y = 0; y < res.rows; y++ )
{
for( int x = 0; x < res.cols; x++ )
{
if( mask.at<uchar>(y+1, x+1) == 0 ) //非0处即为1,表示已经经过填充,不再处理
{
Scalar newVal( rng(256), rng(256), rng(256) );
floodFill( res, mask, Point(x,y), newVal, 0, Scalar::all(5), Scalar::all(5) ); //执行漫水填充
}
}
}
finish=clock();
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<"\n此程序的运行时间为"<<totaltime<<"秒!"<<endl;
// imshow("meanShift图像分割", res );
imshow("res",res);
// waitKey();
return res;
}
void sort_po(Mat src,Mat res, vector <Mat> &outlist ){
vector <Vec3f> Po_value;
vector <Mat> Po;
int count=0;
for(int i=0;i<src.rows;i++){
for(int j=0;j<src.cols;j++){
Vec3f point =src.at<Vec3b>(i, j);
Vec3f point1=(0,0,0);
if (point!=point1) {
count++;
int ju1 = 0;
for (int it = 0; it < Po_value.size(); it++) {
if (point == Po_value[it]) {
Mat tmp = (Mat_<float>(1, 2) << i, j);
Po[it].push_back(tmp);
// cout << 1;
ju1=1;
}
}
if (ju1 == 0) {
Po_value.push_back(point);
Mat tmp2 = (Mat_<float>(1, 2) << i, j);
Po.push_back(tmp2);
}
} else{}
}
}
for (int i1=0 ;i1<Po.size();i1++){
if (Po[i1].rows<count/10){
continue;
} else{
vector<Point > contours;
vector<Point>hull;
for(int i=0;i<Po[i1].rows;i++){
Point tmp=Point(Po[i1].at<float>(i,1),Po[i1].at<float>(i,0));
contours.push_back(tmp);
}
convexHull( contours, hull );
vector<vector<Point> > h={hull};
// Mat tp(res.rows,res.cols,CV_8UC3);
// drawContours( res, h, (int)0, Scalar(255,255,255) ,2);
// imshow("3",res);
// waitKey();
double s=0;
double g_dConArea = contourArea(hull, true);
Mat out=res.clone();
for (int i=0;i<res.rows;i++){
for(int j=0;j<res.cols;j++){
Vec3f value=out.at<Vec3b>(i,j);
if(value==Po_value[i1]){
s++;
out.at<Vec3b>(i,j)=Vec3b(255,255,255);
} else{out.at<Vec3b>(i,j)=Vec3f(0,0,0);}
}
}
if (g_dConArea>0.7*s&&s>0.5*g_dConArea){
outlist.push_back(out);
}
}
}
}
int bSums(Mat src) {
int counter = 0;
//迭代器访问像素点
Mat_<uchar>::iterator it = src.begin<uchar>();
Mat_<uchar>::iterator itend = src.end<uchar>();
for (; it!=itend; ++it)
{
if((*it)>0) counter+=1;//二值化后,像素点是0或者255
}
return counter;
}
Mat firethreold(Mat inImg,int rgb[4]){
Mat fireImg;
fireImg.create(inImg.size(), CV_8UC1);
Mat multiRGB[3];
int a = inImg.channels();
split(inImg, multiRGB); //将图片拆分成R,G,B,三通道的颜色
for (int i = 0; i < inImg.rows; i++)
{
for (int j = 0; j < inImg.cols; j++)
{
float B, G, R;
B = multiRGB[0].at<uchar>(i, j); //每个像素的R,G,B值,动态地址计算法
G = multiRGB[1].at<uchar>(i, j);
R = multiRGB[2].at<uchar>(i, j);
int k=int(sqrt((R-rgb[0])*(R-rgb[0])+(G-rgb[1])*(G-rgb[1])+(B-rgb[2])*(B-rgb[2])));
if (k>255){
k=255;
}
k=255-k;
fireImg.at<uchar>(i, j) = k;
}
}
return fireImg;
}
void kmean_color(Mat pic ,Mat &src,int color_Counts){
const int MAX_CLUSTERS = 5;
float colorTab[] =
{
// Vec3b(0, 0, 255),
// Vec3b(0, 255, 0),
// Vec3b(255, 100, 100),
// Vec3b(255, 0, 255),
// Vec3b(0, 255, 255)
0,
100,
255,
150
};
Mat data,labels;
// Mat pic = imread("d:/woman.png");
for (int i = 0; i < pic.rows;i++)
for (int j = 0; j < pic.cols; j++)
{
uchar point = pic.at<uchar >(i, j);
Mat tmp = (Mat_<float >(1, 1) << point);
data.push_back(tmp);
}
//根据浏览图片,确定k=3
kmeans(data, 3, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0),
3, KMEANS_RANDOM_CENTERS);
int n = 0;
//显示聚类结果,不同的类别用不同的颜色显示
for (int i = 0; i < pic.rows; i++)
for (int j = 0; j < pic.cols; j++)
{
int clusterIdx = labels.at<int>(n);
pic.at<uchar >(i, j) =(uchar)colorTab[clusterIdx];
n++;
}
}
void drawcc(Mat &res){
RNG rng = theRNG();
Mat mask( res.rows+2, res.cols+2, CV_8UC1, Scalar::all(0) ); //掩模
int n=0;
for( int y = 0; y < res.rows; y++ )
{
for( int x = 0; x < res.cols; x++ )
{
if( mask.at<uchar>(y+1, x+1) == 0 ) //非0处即为1,表示已经经过填充,不再处理
{
Scalar newVal( rng(256), rng(256), rng(256) );
floodFill( res, mask, Point(x,y), newVal, 0, Scalar::all(5), Scalar::all(5) ); //执行漫水填充
}
}
}
}
int judgefire(Mat fire){
Mat gray,bin ,candy;
int judge;
cvtColor(fire,gray,CV_BGR2GRAY);
threshold(gray, bin,1, 255, THRESH_BINARY );
Canny( bin, candy, 40, 40*3, 3 );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( bin, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE );
Mat drawing = Mat::zeros( bin.size(), CV_8UC3 );
double k;
// int maxCorners = 5;
// Mat c(bin.rows,bin.cols,CV_8UC1);
// findcorner(c,contours,hierarchy);
// RNG rng(12345);
// vector<Point2f> corners;
// double qualityLevel = 3;
// double minDistance = 50;
// int blockSize = 20, gradientSize = 3;
// bool useHarrisDetector = false;
// double k1 = 0.04;
// Mat copy =bin.clone();
// goodFeaturesToTrack( bin,
// corners,
// maxCorners,
// qualityLevel,
// minDistance,
// Mat(),
// blockSize,
// gradientSize,
// useHarrisDetector,
// k1 );
// cout << "** Number of corners detected: " << corners.size() << endl;
// int radius = 4;
// for( size_t i = 0; i < corners.size(); i++ )
// {
// cout<<corners[i]<<"\n";
// circle( fire, corners[i], radius, Scalar(rng.uniform(0,255), rng.uniform(0, 256), rng.uniform(0, 256)), FILLED );
// }
int coutc=0;
for( size_t i = 0; i< contours.size(); i++ ) {
drawContours(drawing, contours, (int) i, Scalar(255, 0, 0), 2, LINE_8, hierarchy, 0);
if (abs(contourArea(contours[i], true)) > 300) {
if (coutc==1){
judge=0 ;
break;
}
coutc++;
k = arcLength(contours[i], false) * arcLength(contours[i], false) / contourArea(contours[i], true);//k 为不规则度,k越大越不规则;
vector<Vec4i> linesP; // will hold the results of the detection
HoughLinesP(candy, linesP, 1, CV_PI / 180, 50, 50, 10); // runs the actual detection
// Draw the lines
for (size_t i = 0; i < linesP.size(); i++) {
Vec4i l = linesP[i];
line(drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, LINE_AA);
}
// imshow("asd", drawing);
// waitKey();
if (abs(k) <= 40) {
judge = 0;
for (size_t i1 = 0; i1 < linesP.size(); i1++) {
Vec4i l = linesP[i1];
// line( drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
if (abs((l[1] - l[3]) / (l[0] - l[2]+0.1) < 1) ){
judge = 0;
break;
}
// double sita=atan();
}
Rect rect = min_Rect(bin);
cout<<rect.height <<"dwdqa"<< rect.width;
if (rect.height > rect.width * 1.2) {
judge = 1;
} else {
judge = 0;
break;
}
Rect recth = Rect(rect.x, rect.y, (int) (rect.height / 2), rect.width);
Rect rectl = Rect(rect.x, rect.y + (int) (rect.height / 2), (int) (rect.height / 2), rect.width);
int sl = bSums(bin(rectl));
int sh = bSums(bin(recth));
if (sl > 1.2 * sh) {
judge = 1;
} else { judge = 0; }
} else {
judge=1;
vector<Point> hull1;
convexHull( contours[i], hull1 );
int sh=contourArea(hull1, true);
int sa=bSums(bin);
if(sa<0.5*sh){
judge=0;
break;
}
for (size_t i1 = 0; i1 < linesP.size(); i1++) {
Vec4i l = linesP[i1];
// line( drawing, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
if (abs((l[1] - l[3]) / (l[0] - l[2]+0.1)) < 1 || (l[1] - l[3]) / (l[0] - l[2]+0.1) > 20) {
if(sqrt((l[1] - l[3])*(l[1] - l[3])+(l[0] - l[2])*(l[0] - l[2]))>arcLength(contours[i], false)*0.1) {
judge = 0;
break;
}
}
}
}
}
}
// HoughLinesP(candy, linesP, 1, CV_PI/90, 30, 40, 10); // runs the actual detection
// // Draw the lines
// for( size_t i = 0; i < linesP.size(); i++ )
// {
// Vec4i l = linesP[i];
// line(fire, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, LINE_AA);
// }
// imshow("sads",fire);
// cout<<"adwdaw"<<judge<<"\n";
return judge;
}