计算机视觉课程作业

计算机视觉课程(Win10+OpenCV+Qt)

说明

为记录研一计算机视觉课程作业代码而写,工程名为week1_qt,算是图像处理的入门,代码里可能有一些错误(原理或代码编写)

week1_qt.h

#ifndef WEEK1_QT_H
#define WEEK1_QT_H

#include <QtWidgets/QMainWindow>
#include "ui_week1_qt.h"
#include <opencv2/opencv.hpp> 
#include <QImage>
#include <QPixmap>
#include <QFileDialog>
#include <QMessageBox>
#include <QScreen>
#include <QGuiApplication>
#include<QGraphicsScene>  
#include<QGraphicsView>                   //graphicsview类
#include<opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>  //opencv申明
#include <qfiledialog.h>                //getopenfilename 类申明
#include <qlabel.h>  
//QT_CHARTS_USE_NAMESPACE
class week1_qt : public QMainWindow
{
	Q_OBJECT
    
public:
	week1_qt(QWidget *parent = 0);
	~week1_qt();
	//自定义变量
	cv::Mat src;
private:
	Ui::week1_qtClass ui;
	//自定义变量
	cv::Mat image;
    QLabel *label = new QLabel;
//信号函数
signals:
//槽函数
private slots:
	//第一次作业
    void pushButton_1_clicked();
    void pushButton_2_clicked();
	void pushButton_3_clicked();
	void pushButton_4_clicked();
	void pushButton_5_clicked();
	//第二次作业
	//1、去噪处理
	//添加椒盐噪声
	cv::Mat addSaltNoise();
	//添加高斯噪声
	cv::Mat addGaussianNoise();
	//均值滤波
	void my_MeanBlur();
	//最大最小值滤波
	void my_MaxMinBlur();
	//中值滤波
	void my_MedianBlur();
	//2、阈值分割
	void my_threshold();//可变阈值
	void fengemianji();
	//3、拉伸变换
	//分段线性拉伸
	void dividedLinearStrength();
	//直方图拉伸
	void zhifangtulashen();
	//4、区域生长法
	void RegionGrow();
	//第三次作业
	//1、边缘检测
	//sobel算子
	void my_sobel();
	//canny算子
	void my_prewitt();
	//laplace算子
	void my_roberts();
	//2、边界提取
	void my_boder();
	//3、骨架提取
	void gujiatiqu();
	//第四次作业
	//1、腐蚀膨胀
	void fushipengzhang();
	//2、直线检测
	void line_detect();
	//3、应用
	void lvbo();
	//第五次作业
	//1、2、边界线链码及周长面积计算
	void lianma();
	//3、共生矩阵及特征
	void gongsheng();
};
#endif // WEEK1_QT_H

main.cpp

#include "week1_qt.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	week1_qt w;
	w.show();
	return a.exec();
}

week1_qt.cpp

#include "week1_qt.h"
#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>
#include<stack>
//#pragma execution_character_set("utf-8")    // 解决汉字乱码问题,注意!!!
using namespace std;
using namespace cv;
//区域生长法
static Point connects[8] = { Point(-1, -1), Point(0, -1), Point(1, -1), Point(1, 0), Point(1, 1), Point(0, 1), Point(-1, 1), Point(-1, 0) };
Mat src_threshold;
Mat dst_threshold;
int thresholdValue = 100;
int w = 0;
int b = 0;
//主函数
week1_qt::week1_qt(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
}
week1_qt::~week1_qt()
{
	
}
//第一次作业
//普通函数
//彩色图像灰度化处理(采用加权法)
Mat RGB2GRAY(Mat src)
{
	if (src.channels() == 1)
	{
		return src;
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		//参数及初始化
		Mat dst(src.rows, src.cols, CV_8UC1, Scalar(255));
		double B, G, R;
		B = 0.114;
		G = 0.587;
		R = 0.299;
		int b_val, g_val, r_val;
		//赋值
		for (int i = 0; i < src.rows; i++)
		{
			for (int j = 0; j < src.cols; j++)
			{
				b_val = src.at<Vec3b>(i, j)[0];
				g_val = src.at<Vec3b>(i, j)[1];
				r_val = src.at<Vec3b>(i, j)[2];
				dst.at<uchar>(i, j) = saturate_cast<uchar>(B*b_val + G*g_val + R*r_val);
			}
		}
		return dst;
	}
	else
	{
		throw "error";
	}
	//cvtColor(src, dst, COLOR_BGR2GRAY, 0);
}
//灰度直方图(灰度图,彩图)
Mat Histogram(Mat src)
{
	//灰度图
	if (src.channels() == 1)
	{
		//参数准备
		Mat dstHist;
		int channels = 0;
		int dims = 1;
		int Num = 256;
		int size[] = { Num };
		float hranges[] = { 0,255 };
		const float *ranges[] = { hranges };
		//计算图像直方图
		calcHist(&src, 1, &channels, Mat(), dstHist, dims, size, ranges);
		int scale = 1;
		Mat dst(Num * scale, Num, CV_8U, Scalar(0));
		//获取最大值和最小值
		double minValue = 0;
		double maxValue = 0;
		minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);
		//绘制出直方图
		int hpt = saturate_cast<int>(0.9 * Num);
		for (int i = 0; i < Num; i++)
		{
			float binValue = dstHist.at<float>(i);
			int realValue = saturate_cast<int>(binValue * hpt / maxValue);
			rectangle(dst, Point(i * scale, Num - 1), Point((i + 1)*scale - 1, Num - realValue), Scalar(255));
		}
		return dst;
	}
	else if (src.channels() == 3 || src.channels() == 4)
	{
		//参数准备
		int bins = 256;
		int hist_size[] = { bins };
		float range[] = { 0, 256 };
		const float* ranges[] = { range };
		Mat redHist, grayHist, blueHist;
		//直方图计算(红色部分)
		int channels_r[] = { 0 };
		calcHist(&src, 1, channels_r, Mat(), redHist, 1, hist_size, ranges);
		//直方图计算(绿色部分)
		int channels_g[] = { 1 };
		calcHist(&src, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges);
		//直方图计算(蓝色部分)
		int channels_b[] = { 2 };
		calcHist(&src, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges);
		//绘制三色直方图
		//1、参数准备
		double maxValue_red, maxValue_green, maxValue_blue;
		minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
		minMaxLoc(grayHist, 0, &maxValue_green, 0, 0);
		minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0);
		int scale = 1;
		int histHeight = 256;
		Mat dst = Mat::zeros(histHeight, bins * 3, CV_8UC3);
		//2、正式绘制
		for (int i = 0; i<bins; i++)
		{
			//参数准备
			float binValue_red = redHist.at<float>(i);
			float binValue_green = grayHist.at<float>(i);
			float binValue_blue = blueHist.at<float>(i);
			int intensity_red = cvRound(binValue_red*histHeight / maxValue_red);  //要绘制的高度
			int intensity_green = cvRound(binValue_green*histHeight / maxValue_green);  //要绘制的高度
			int intensity_blue = cvRound(binValue_blue*histHeight / maxValue_blue);  //要绘制的高度																 //绘制红色分量的直方图
			rectangle(dst, Point(i*scale, histHeight - 1), Point((i + 1)*scale - 1, histHeight - intensity_red), Scalar(255, 0, 0));
			//绘制绿色分量的直方图
			rectangle(dst, Point((i + bins)*scale, histHeight - 1), Point((i + bins + 1)*scale - 1, histHeight - intensity_green), Scalar(0, 255, 0));
			//绘制蓝色分量的直方图
			rectangle(dst, Point((i + bins * 2)*scale, histHeight - 1), Point((i + bins * 2 + 1)*scale - 1, histHeight - intensity_blue), Scalar(0, 0, 255));
		}
		return dst;
	}
	else
	{
		throw "error";
	}
}
//灰度图像的伪彩图像
Mat GRAY2RGB(Mat src)
{
	if (src.channels() == 1)
	{
		//参数初始化
		Mat dst(src.rows, src.cols, CV_8UC3, Scalar(0, 0, 0));
		uchar r_val, g_val, b_val;
		uchar gray_val;
		//色彩转换
		for (int i = 0; i < src.rows; i++)
		{
			for (int j = 0; j < src.cols; j++)
			{
				gray_val = src.at<uchar>(i, j);
				//计算RGB通道像素值
				if ((gray_val >= 0) && (gray_val <= 63))
				{
					r_val = 0;
					g_val = saturate_cast<uchar>(254 - 4 * gray_val);
					b_val = 255;
				}
				else if ((gray_val >= 64) && (gray_val <= 127))
				{
					r_val = 0;
					g_val = saturate_cast<uchar>(4 * gray_val - 254);
					b_val = saturate_cast<uchar>(510 - 4 * gray_val);
				}
				else if ((gray_val >= 128) && (gray_val <= 191))
				{
					r_val = saturate_cast<uchar>(4 * gray_val - 510);
					g_val = 255;
					b_val = 0;
				}
				else if ((gray_val >= 192) && (gray_val <= 255))
				{
					r_val = 255;
					g_val = saturate_cast<uchar>(1022 - 4 * gray_val);
					b_val = 0;
				}
				else
				{
					throw "red error";
				}
				//赋值
				dst.at<Vec3b>(i, j)[2] = r_val;
				dst.at<Vec3b>(i, j)[1] = g_val;
				dst.at<Vec3b>(i, j)[0] = b_val;
			}
		}
		return dst;
	}
	else if (src.channels() == 3 || src.channels() == 4)
	{
		return src;
	}
	else
	{
		throw "error";
	}
}
//信号与槽函数
//槽函数
//读入图片
void week1_qt::pushButton_1_clicked()         
{
	QString fileName = QFileDialog::getOpenFileName(this, tr("File Dialog"), "E:", tr("pic file(* png * jpg * bmp)"));
	//判断是否有选择文件
	if ("" == fileName) return;
	//读取文件,并把QString类型转化为string
	src = imread(string((const char *)fileName.toLocal8Bit()));
	//显示图片
	imshow("原图", src);
	waitKey(0);
}
//灰度图
void week1_qt::pushButton_2_clicked()
{
	Mat dst1 = RGB2GRAY(src);
	imshow("灰度图", dst1);
}
//直方图
void week1_qt::pushButton_3_clicked()
{
	Mat dst2 = Histogram(src);
	imshow("彩色直方图", dst2);
	Mat dst3 = Histogram(RGB2GRAY(src));
	imshow("灰度直方图", dst3);
	waitKey(0);
}
//伪彩图
void week1_qt::pushButton_4_clicked()
{
	Mat dst4 = GRAY2RGB(RGB2GRAY(src));
	imshow("伪彩图", dst4);
}
void week1_qt::pushButton_5_clicked()
{
	Mat dst1 = RGB2GRAY(src);
	Mat dst2 = Histogram(src);
	Mat dst3 = Histogram(RGB2GRAY(src));
	Mat dst4 = GRAY2RGB(RGB2GRAY(src));
	imwrite("原图.jpg", src);
	imwrite("灰度图.jpg", dst1);
	imwrite("彩图直方图.jpg", dst2);
	imwrite("灰度直方图.jpg", dst3);
	imwrite("灰度伪彩图.jpg", dst4);
}
//第二次作业
//1、图像去噪
//添加椒盐噪声
Mat week1_qt::addSaltNoise()
{
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg");
	imshow("滤波原图", src);
	int n = 1500;//n为添加多少个噪声点
	Mat dst = src.clone();
	for (int k = 0; k < n; k++)
	{
		//随机取值行列
		int i = rand() % dst.rows;
		int j = rand() % dst.cols;
		//图像通道判定
		if (dst.channels() == 1)
		{
			dst.at<uchar>(i, j) = 255;		//盐噪声
		}
		else
		{
			dst.at<Vec3b>(i, j)[0] = 255;
			dst.at<Vec3b>(i, j)[1] = 255;
			dst.at<Vec3b>(i, j)[2] = 255;
		}
	}
	for (int k = 0; k < n; k++)
	{
		//随机取值行列
		int i = rand() % dst.rows;
		int j = rand() % dst.cols;
		//图像通道判定
		if (dst.channels() == 1)
		{
			dst.at<uchar>(i, j) = 0;		//椒噪声
		}
		else
		{
			dst.at<Vec3b>(i, j)[0] = 0;
			dst.at<Vec3b>(i, j)[1] = 0;
			dst.at<Vec3b>(i, j)[2] = 0;
		}
	}
	imshow("椒盐噪声图", dst);
	return dst;
}
//添加高斯噪声
//生成高斯噪声
double generateGaussianNoise(double m, double sigma)//m为均值,sigma为方差
{
	//定义小值
	const double epsilon = numeric_limits<double>::min();//返回的是编译器定义的最小的双精度浮点数
	static double z0, z1;
	static bool flag = false;
	flag = !flag;
	//flag为假,构造高斯随机变量X
	if (!flag)
		return z1 * sigma + m;
	double u1, u2;
	//构造随机变量
	do
	{
		u1 = rand() * (1.0 / RAND_MAX);
		u2 = rand() * (1.0 / RAND_MAX);
	} while (u1 <= epsilon);
	//flag为真,构造高斯随机变量
	z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);
	z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);
	return z0 * sigma + m;
}
//为图像添加高斯噪声
Mat week1_qt::addGaussianNoise()
{
	double generateGaussianNoise(double m, double sigma);
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg");
	double m = 0;
	double sigma = 8;
	Mat dst = src.clone();
	int channels = dst.channels();
	int rowsNumber = dst.rows;
	int colsNumber = dst.cols * channels;
	//推断图像的连续性
	if (dst.isContinuous())
	{
		colsNumber *= rowsNumber;
		rowsNumber = 1;
	}
	for (int i = 0; i < rowsNumber; i++)
	{
		for (int j = 0; j < colsNumber; j++)
		{
			//加入高斯噪声
			int val = dst.ptr<uchar>(i)[j] + generateGaussianNoise(m, sigma);
			if (val < 0)
				val = 0;
			if (val>255)
				val = 255;
			dst.ptr<uchar>(i)[j] = (uchar)val;
		}
	}
	imshow("高斯噪声", dst);
	return dst;
}
//均值滤波(高斯噪声)
void  week1_qt::my_MeanBlur()
{
	Mat img = week1_qt::addGaussianNoise();
	int sizey =img.cols;                                             //读取图像大小
	int sizex = img.rows;
	Mat junzhi = Mat(sizex, sizey, CV_8UC1);//创建均值滤波图像
	Mat gray = Mat(sizex, sizey, CV_8UC1);//创建灰度图
	if (img.channels() == 1)
	{
		gray = img.clone();
	}
	else if (img.channels() == 3 || img.channels() == 4)//第四通道表示透明度
	{
		cvtColor(img, gray, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	//均值滤波
	imshow("加高斯噪声的灰度图", gray);
	for (int x = 1; x < sizex - 1; x++)
	{
		for (int y = 1; y < sizey - 1; y++)
		{
			int xp = x + 1;
			int yp = y + 1; 
			int xm = x - 1;
			int ym = y - 1; 
			junzhi.at<uchar>(x, y) = (gray.at<uchar>(xm, ym) + gray.at<uchar>(x, ym) + gray.at<uchar>(xp, ym) + gray.at<uchar>(xm, y) + gray.at<uchar>(x, y) + gray.at<uchar>(xp, y) + gray.at<uchar>(xm, yp) + gray.at<uchar>(x, yp) + gray.at<uchar>(xp, yp)) / 9;
		}
	}
	imshow("均值滤波(高斯噪声)", junzhi);
}
//最大最小值滤波(椒盐噪声)
void week1_qt::my_MaxMinBlur()
{
	Mat img = week1_qt::addSaltNoise();
	int sizey = img.cols;                                             //读取图像大小
	int sizex = img.rows;
	Mat zuidazuixiaozhi = Mat(sizex, sizey, CV_8UC1);//创建最大最小值滤波图像
	Mat gray = Mat(sizex, sizey, CV_8UC1);//创建灰度图
	if (img.channels() == 1)
	{
		gray = img.clone();
	}
	else if (img.channels() == 3 || img.channels() == 4)//第四通道表示透明度
	{
		cvtColor(img, gray, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	//最大最小值滤波
	imshow("加椒盐噪声的灰度图", gray);
	for (int x = 1; x < sizex - 1; x++)
	{
		for (int y = 1; y < sizey - 1; y++)
		{
			int xp = x + 1;
			int yp = y + 1;
			int xm = x - 1;
			int ym = y - 1;
			int kernal[9] = { 0 };
			kernal[0] = gray.at<uchar>(xm, ym); kernal[1] = gray.at<uchar>(x, ym); kernal[2] = gray.at<uchar>(xp, ym);
			kernal[3] = gray.at<uchar>(xm, y); kernal[4] = gray.at<uchar>(x, y); kernal[5] = gray.at<uchar>(xp, y);
			kernal[6] = gray.at<uchar>(xm, yp); kernal[7] = gray.at<uchar>(x, yp); kernal[8] = gray.at<uchar>(xp, yp);
			zuidazuixiaozhi.at<uchar>(x, y) = kernal[4];
			for (int i = 0; i < 9; i++)
			{
				for (int j = i + 1; j < 9; j++)
				{
					if (kernal[i]<kernal[j])    //如果前一个元素小于后一个元素
					{
						int temp;        //临时变量
						temp = kernal[i];
						kernal[i] = kernal[j]; //大的元素到前一个位置
						kernal[j] = temp;   //小的元素到后一个位置
					}
				}
			}
			if (gray.at<uchar>(x, y) == kernal[8])
			{
				zuidazuixiaozhi.at<uchar>(x, y) = kernal[7];
			}
			if (gray.at<uchar>(x, y) == kernal[0])
			{
				zuidazuixiaozhi.at<uchar>(x, y) = kernal[1];
			}

		}
	}
	imshow("最大最小值滤波(椒盐噪声)", zuidazuixiaozhi);
}
//中值滤波(椒盐噪声)
void week1_qt::my_MedianBlur()
{
	Mat img = week1_qt::addSaltNoise();
	int sizey = img.cols;                                             //读取图像大小
	int sizex = img.rows;
	Mat zhongzhi = Mat(sizex, sizey, CV_8UC1);//创建中值滤波图像
	Mat gray = Mat(sizex, sizey, CV_8UC1);//创建灰度图
	if (img.channels() == 1)
	{
		gray = img.clone();
	}
	else if (img.channels() == 3 || img.channels() == 4)//第四通道表示透明度
	{
		cvtColor(img, gray, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	//中值滤波
	imshow("加椒盐噪声的灰度图", gray);
	for (int x = 1; x < sizex - 1; x++)
	{
		for (int y = 1; y < sizey - 1; y++)
		{
			int xp = x + 1;
			int yp = y + 1;
			int xm = x - 1;
			int ym = y - 1;
			int kernal[9] = { 0 };
			kernal[0] = gray.at<uchar>(xm, ym); kernal[1] = gray.at<uchar>(x, ym); kernal[2] = gray.at<uchar>(xp, ym);
			kernal[3] = gray.at<uchar>(xm, y); kernal[4] = gray.at<uchar>(x, y); kernal[5] = gray.at<uchar>(xp, y);
			kernal[6] = gray.at<uchar>(xm, yp); kernal[7] = gray.at<uchar>(x, yp); kernal[8] = gray.at<uchar>(xp, yp);
			for (int i = 0; i < 9; i++)
			{
				for (int j = i + 1; j < 9; j++)
				{
					if (kernal[i]<kernal[j])    //如果前一个元素小于后一个元素
					{
						int temp;        //临时变量
						temp = kernal[i];
						kernal[i] = kernal[j]; //大的元素到前一个位置
						kernal[j] = temp;   //小的元素到后一个位置
					}
				}
			}
			zhongzhi.at<uchar>(x, y) = kernal[4];
		}
	}
	imshow("中值滤波(椒盐噪声)", zhongzhi);
}
//2、阈值分割
//阈值分割回调函数
void on_my_throwshold(int, void*)
{
	//threshold(src_threshold, dst_threshold, thresholdValue, 255, 0);
	dst_threshold = src_threshold.clone();
	//分割图像并计算面积
	w = 0;//注意:不然会累加
	b = 0;
	for (int i = 0; i < src_threshold.rows; i++)
	{
		for (int j = 0; j < src_threshold.cols; j++)
		{
			if ((src_threshold.at<uchar>(i, j))>thresholdValue)
			{
				dst_threshold.at<uchar>(i, j) = 255;
				w++;
			}
			else
			{
				dst_threshold.at<uchar>(i, j) = 0;
				b++;
			}
		}
	}
	imshow("阈值分割", dst_threshold);
}
//阈值分割
void week1_qt::my_threshold()
{
	thresholdValue = 100;
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg");
	if (src.channels() == 1)
	{
		src_threshold = src.clone();
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		cvtColor(src, src_threshold, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	//void on_my_throwshold(int, void*);
	namedWindow("阈值分割", 1);
	createTrackbar("阈值", "阈值分割", &thresholdValue, 255, on_my_throwshold);
	on_my_throwshold(thresholdValue, 0);
}

void week1_qt::fengemianji()
{
	ui.textBrowser->insertPlainText(tr("black:%1--------").arg(b));
	ui.textBrowser->insertPlainText(tr("white:%1\n").arg(w));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}
//3、拉伸变换
//分段线性拉伸
void week1_qt::dividedLinearStrength()
{
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg", 0);
	imshow("原图灰度图", src);
	float x1 = 10;
	float y1 = 50;
	float x2 = 200;
	float y2 = 150;
	//计算直线参数
	//L1
	float K1 = y1 / x1;
	//L2
	float K2 = (y2 - y1) / (x2 - x1);
	float B2 = y1 - K2 * x1;
	//L3
	float K3 = (255.0f - y2) / (255.0f - x2);
	float B3 = 255.0f - K3 * 255.0f;
	Mat dst = src.clone();
	if (src.channels() == 1)
	{
		dst = src.clone();
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		cvtColor(src, dst, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	//拉伸过程
	for (int i = 0; i < dst.rows; i++)
	{
		for (int j = 0; j < dst.cols; j++)
		{
			if (dst.at<uchar>(i, j) <= x1)
			{
				dst.at<uchar>(i, j) = K1*dst.at<uchar>(i, j);
			}
			else if ((dst.at<uchar>(i, j)>x1) || (dst.at<uchar>(i, j) <= x2))
			{
				dst.at<uchar>(i, j) = K2 * dst.at<uchar>(i, j) + B2;
			}
			else
			{
				dst.at<uchar>(i, j) = K3 * dst.at<uchar>(i, j) + B3;
			}
		}
	}
	imshow("分段线性拉伸图", dst);
	//方差显示
	double getVar(Mat src);
	double v1 = getVar(src);
	double v2 = getVar(dst);
	
	ui.textBrowser->insertPlainText(tr("src:%1--------").arg(v1));
	ui.textBrowser->insertPlainText(tr("dst:%1\n").arg(v2));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}
//计算图像方差
double getVar(Mat src)
{
	double var;
	Mat dst;
	if (src.channels() == 1)
	{
		dst = src.clone();
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		cvtColor(src, dst, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	Mat mean;
	Mat stdDev;
	meanStdDev(dst, mean, stdDev);
	double avg, stddev;
	avg = mean.ptr<double>(0)[0];
	stddev = stdDev.ptr<double>(0)[0];
	return stddev * stddev;
}
void week1_qt::zhifangtulashen()
{
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg", 0);
	//原图直方图绘制
	//参数准备
	Mat dstHist;
	int channels = 0;
	int dims = 1;
	int Num = 256;
	int size[] = { Num };
	float hranges[] = { 0,255 };
	const float *ranges[] = { hranges };
	//计算图像直方图
	calcHist(&src, 1, &channels, Mat(), dstHist, dims, size, ranges);
	int scale = 1;
	Mat dst(Num * scale, Num, CV_8U, Scalar(0));
	//获取最大值和最小值
	double minValue = 0;
	double maxValue = 0;
	minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);
	//ui.textBrowser->insertPlainText(tr("dst:%1\n").arg(maxValue));
	//绘制出直方图
	int hpt = saturate_cast<int>(0.9 * Num);
	for (int i = 0; i < Num; i++)
	{
		float binValue = dstHist.at<float>(i);
		int realValue = saturate_cast<int>(binValue * hpt / maxValue);
		rectangle(dst, Point(i * scale, Num - 1), Point((i + 1)*scale - 1, Num - realValue), Scalar(255));
	}
	imshow("原灰度图", src);
	imshow("原图直方图", dst);
	//直方图拉伸变换
	int threshold = 2000;
	Mat lashen = src.clone();//拉伸图像
	Mat lashenHist ;//拉伸直方图
	//求左边界
	int grayMin = 0;
	for (int i = 0; i < 256; i++)
	{
		float binValue = dstHist.at<float>(i);
		if (binValue > threshold)
		{
			grayMin = i;
			break;
		}
		//ui.textBrowser->insertPlainText(tr("dst:%1\n").arg(binValue));
	}
	//求右边界
	int grayMax = 0;
	for (int i = 255; i >= 0; i--)
	{
		float binValue = dstHist.at<float>(i);
		if (binValue > threshold)
		{
			grayMax = i;
			break;
		}
	}
	int a = 0;
	int z = 0;
	for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			int value = src.at<uchar>(i, j);
			if (value < grayMin)
			{
				lashen.at<uchar>(i, j) = 0;
			}
			else if (value > grayMax)
			{
				lashen.at<uchar>(i, j) = 255;
			}
			else
			{
				lashen.at<uchar>(i, j) = (value - grayMin) * 255 / (grayMax - grayMin);
			}
		}
	}
	imshow("直方图拉伸图像", lashen);
	lashenHist = Histogram(lashen);
	imshow("直方图拉伸灰度图", lashenHist);
	double v1 = getVar(src);
	double v2 = getVar(lashen);

	ui.textBrowser->insertPlainText(tr("src:%1--------").arg(v1));
	ui.textBrowser->insertPlainText(tr("dst:%1\n").arg(v2));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}
//4、区域生长法
void week1_qt::RegionGrow()
{
	Mat src = imread("E:/opencv project/homework/week1/data/2.jpg");
	Mat srcc;
	int th = 30;//阈值
				// 原图
	if (src.channels() == 1)
	{
		srcc = src.clone();
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		cvtColor(src, srcc, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}

	imshow("区域生长原灰度图", srcc);
	// 结果图
	Mat res = Mat::zeros(srcc.rows, srcc.cols, CV_8U);
	// 用于标记是否遍历过某点
	Mat flagMat;
	res.copyTo(flagMat);
	// 初始3个种子点,任选
	stack<Point> seeds;
	seeds.push(Point(0, 0));
	seeds.push(Point(186, 166));
	seeds.push(Point(327, 43));
	res.at<uchar>(0, 0) = 255;
	res.at<uchar>(166, 186) = 255;
	res.at<uchar>(43, 327) = 255;

	while (!seeds.empty())
	{
		Point seed = seeds.top();
		seeds.pop();
		// 标记为已遍历过的点
		flagMat.at<uchar>(seed.y, seed.x) = 1;
		// 遍历8邻域
		for (size_t i = 0; i < 8; i++)
		{
			int tmpx = seed.x + connects[i].x;
			int tmpy = seed.y + connects[i].y;
			if (tmpx < 0 || tmpy < 0 || tmpx >= srcc.cols || tmpy >= srcc.rows)
				continue;
			// 前景点(邻域所有像素差值均小于阈值)且没有被标记过的点
			if ((abs(srcc.at<uchar>(seed.y, seed.x) - res.at<uchar>(tmpy, tmpx)) < th) && flagMat.at<uchar>(tmpy, tmpx) == 0)
			{
				res.at<uchar>(tmpy, tmpx) = 255; // 生长
				flagMat.at<uchar>(tmpy, tmpx) = 1; // 标记
				seeds.push(Point(tmpx, tmpy)); // 种子压栈
			}
		}
	}
	imshow("区域生长法", res);
}
//第三次作业
//边缘检测
//sobel算子
void week1_qt::my_sobel()
{
	Mat image = imread("E:/opencv project/homework/week1/data/2.jpg", 0);
	imshow("边缘检测原图", image);
	Mat imageX = Mat::zeros(image.size(), CV_16SC1);
	Mat imageY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageXY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageX8UC;
	Mat imageY8UC;
	Mat imageXY8UC;
	GaussianBlur(image, image, Size(3, 3), 0); //高斯滤波消除噪点
	uchar *P = image.data;
	uchar *PX = imageX.data;
	uchar *PY = imageY.data;
	int step = image.step;
	int stepXY = imageX.step;
	for (int i = 1; i<image.rows - 1; i++)
	{
		for (int j = 1; j<image.cols - 1; j++)
		{
			//通过指针遍历图像上每一个像素
			PX[i*imageX.step + j*(stepXY / step)] = abs(P[(i - 1)*step + j + 1] + P[i*step + j + 1] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[i*step + j - 1] * 2 - P[(i + 1)*step + j - 1]);
			PY[i*imageX.step + j*(stepXY / step)] = abs(P[(i + 1)*step + j - 1] + P[(i + 1)*step + j] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[(i - 1)*step + j] * 2 - P[(i - 1)*step + j + 1]);
		}
	}
	addWeighted(imageX, 0.5, imageY, 0.5, 0, imageXY);//融合X、Y方向	
	convertScaleAbs(imageX, imageX8UC);
	convertScaleAbs(imageY, imageY8UC);
	convertScaleAbs(imageXY, imageXY8UC);   //转换为8bit图像
	imshow("sobel算子", imageXY8UC);
}
//prewitt算子
void week1_qt::my_prewitt()
{
	Mat image = imread("E:/opencv project/homework/week1/data/2.jpg", 0);
	Mat imageX = Mat::zeros(image.size(), CV_16SC1);
	Mat imageY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageXY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageX8UC;
	Mat imageY8UC;
	Mat imageXY8UC;
	GaussianBlur(image, image, Size(3, 3), 0); //高斯滤波消除噪点
	uchar *P = image.data;
	uchar *PX = imageX.data;
	uchar *PY = imageY.data;
	int step = image.step;
	int stepXY = imageX.step;
	for (int i = 1; i<image.rows - 1; i++)
	{
		for (int j = 1; j<image.cols - 1; j++)
		{
			//通过指针遍历图像上每一个像素
			PX[i*imageX.step + j*(stepXY / step)] = abs(P[(i - 1)*step + j + 1] + P[i*step + j + 1] + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[i*step + j - 1] - P[(i + 1)*step + j - 1]);
			PY[i*imageX.step + j*(stepXY / step)] = abs(P[(i + 1)*step + j - 1] + P[(i + 1)*step + j] + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[(i - 1)*step + j] - P[(i - 1)*step + j + 1]);
		}
	}
	addWeighted(imageX, 0.5, imageY, 0.5, 0, imageXY);//融合X、Y方向	
	convertScaleAbs(imageX, imageX8UC);
	convertScaleAbs(imageY, imageY8UC);
	convertScaleAbs(imageXY, imageXY8UC);   //转换为8bit图像
	imshow("prewitt算子", imageXY8UC);
}
//roberts算子
void week1_qt::my_roberts()
{
	Mat image = imread("E:/opencv project/homework/week1/data/2.jpg", 0);
	Mat imageX = Mat::zeros(image.size(), CV_16SC1);
	Mat imageY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageXY = Mat::zeros(image.size(), CV_16SC1);
	Mat imageX8UC;
	Mat imageY8UC;
	Mat imageXY8UC;
	GaussianBlur(image, image, Size(3, 3), 0); //高斯滤波消除噪点
	uchar *P = image.data;
	uchar *PX = imageX.data;
	uchar *PY = imageY.data;
	int step = image.step;
	int stepXY = imageX.step;
	for (int i = 1; i<image.rows - 1; i++)
	{
		for (int j = 1; j<image.cols - 1; j++)
		{
			//通过指针遍历图像上每一个像素
			PX[i*imageX.step + j*(stepXY / step)] = abs(P[(i + 1)*step + j + 1] - P[i*step + j]);
			PY[i*imageX.step + j*(stepXY / step)] = abs(P[i*step + j + 1] - P[(i + 1)*step + j]);
		}
	}
	addWeighted(imageX, 0.5, imageY, 0.5, 0, imageXY);//融合X、Y方向	
	convertScaleAbs(imageX, imageX8UC);
	convertScaleAbs(imageY, imageY8UC);
	convertScaleAbs(imageXY, imageXY8UC);   //转换为8bit图像
	imshow("roberts算子", imageXY8UC);
}
//2、二值图像及其边界提取
void week1_qt::my_boder()
{
	Mat src = imread("E:/opencv project/homework/week1/data/3.jpg");
	imshow("边界提取原图", src);
	//转成二值图像
	Mat src_boder;
	if (src.channels() == 1)
	{
		src_boder = src.clone();
	}
	else if (src.channels() == 3 || src.channels() == 4)//第四通道表示透明度
	{
		cvtColor(src, src_boder, CV_RGB2GRAY);
	}
	else
	{
		throw "error";
	}
	threshold(src_boder, src_boder, 150, 255, THRESH_BINARY);
	//腐蚀操作
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	Mat dst;
	erode(src_boder, dst, element);
	//相减
	absdiff(src_boder, dst, dst);
	imshow("边界提取", dst);
	//计算各分割图像面积及边界长度
	vector<vector<Point>> g_vContours;
	vector<Vec4i> g_vHierarchy;
	//找到轮廓
	findContours(dst, g_vContours, g_vHierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
	/*
	//计算矩
	vector<Moments> mu(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		mu[i] = moments(g_vContours[i], false);
		//
	}
	//计算中心矩
	vector<Point2f> mc(g_vContours.size());
	for (unsigned int i = 0; i < g_vContours.size(); i++)
	{
		mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
	}
	*/
	//计算轮廓长度面积
	for (int i = 0; i < g_vContours.size(); i++)
	{
		double area1 = contourArea(g_vContours[i]);
		double length1 = arcLength(g_vContours[i], true);
		ui.textBrowser->insertPlainText(tr("boder's length:%1--------").arg(length1));
		ui.textBrowser->insertPlainText(tr("area :%1\n").arg(area1));
		ui.textBrowser->moveCursor(QTextCursor::Start);
	}
	/*
	Mat Inputimage = dst;
	int a[1000];
	int m = 0, n;
	map<int, int> colors;
	int rows = Inputimage.rows;
	int cols = Inputimage.cols;
	for (int i = 0; i < rows; i++)
	{
		const int* data_src = (int*)Inputimage.ptr<int>(i);
		for (int j = 0; j < cols; j++)
		{
			int pixelValue = data_src[j];
			if (pixelValue > 1)
			{
				if (colors.count(pixelValue) <= 0)
				{
					colors[pixelValue] = m;
					a[m] = 0;
					m++;
				}
				n = colors[pixelValue];
				a[n]++;
			}
		}
	}
	for (int o = 0; o < m; o++)
		if (a[o] > 600)
		{
			ui.textBrowser->insertPlainText(tr("boder's length:%1--------").arg(a[o] / 4));
			ui.textBrowser->insertPlainText(tr("area :%1\n").arg(a[o]));
			ui.textBrowser->moveCursor(QTextCursor::Start);
		}
		*/
}
//3、区域骨架提取
void week1_qt::gujiatiqu()
{
	//读入灰度图像
	Mat src = imread("E:/opencv project/homework/week1/data/4.jpg", 0);
	imshow("原始图像", src);
	//二值化处理
	GaussianBlur(src, src, Size(7, 7), 0, 0);//高斯滤波
	threshold(src, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	vector<Point2i> point1;
	while (1)
	{
		//计算删除点个数
		int c0 = 0;
		//进行第一遍条件检测,判断是否删除该白点
		for (int x = 1; x < src.rows - 1; x++)
		{
			for (int y = 1; y < src.cols - 1; y++)
			{
				//白点
				if (src.at<uchar>(x, y) == 1)
				{
					//计算条件一:黑点数2和6之间
					int c1 = 0;
					c1 = src.at<uchar>(x - 1, y - 1) + src.at<uchar>(x, y - 1) + src.at<uchar>(x + 1, y - 1) + src.at<uchar>(x - 1, y) + src.at<uchar>(x + 1, y) + src.at<uchar>(x - 1, y + 1) + src.at<uchar>(x, y + 1) + src.at<uchar>(x + 1, y + 1);
					//c1 = 8 - c1;
					if (c1 >= 2 && c1 <= 6)
					{
						//计算条件二:顺时针0,1个数为1
						int c2 = 0;
						if (src.at<uchar>(x - 1, y - 1) == 0 && src.at<uchar>(x, y - 1) == 1) ++c2;
						if (src.at<uchar>(x, y - 1) == 0 && src.at<uchar>(x + 1, y - 1) == 1) ++c2;
						if (src.at<uchar>(x + 1, y - 1) == 0 && src.at<uchar>(x + 1, y) == 1) ++c2;
						if (src.at<uchar>(x + 1, y) == 0 && src.at<uchar>(x + 1, y + 1) == 1) ++c2;
						if (src.at<uchar>(x + 1, y + 1) == 0 && src.at<uchar>(x, y + 1) == 1) ++c2;
						if (src.at<uchar>(x, y + 1) == 0 && src.at<uchar>(x - 1, y + 1) == 1) ++c2;
						if (src.at<uchar>(x - 1, y + 1) == 0 && src.at<uchar>(x - 1, y) == 1) ++c2;
						if (src.at<uchar>(x - 1, y) == 0 && src.at<uchar>(x - 1, y - 1) == 1) ++c2;
						if (c2 == 1)
						{
							//计算条件三:p2*p4*p6=0
							int c3 = src.at<uchar>(x, y - 1)*src.at<uchar>(x + 1, y)*src.at<uchar>(x, y + 1);
							if (c3 == 0)
							{
								//计算条件四:p4*p6*p8=0
								int c4 = src.at<uchar>(x - 1, y)*src.at<uchar>(x + 1, y)*src.at<uchar>(x, y + 1);
								if (c4 == 0)
								{
									//删掉该点
									//src.at<uchar>(x, y) = 0;
									Point2i p;
									p.x = x;
									p.y = y;
									point1.push_back(p);
									c0++;
								}
							}
						}
					}
				}
			}
		}
		for (vector<Point2i>::iterator i = point1.begin(); i != point1.end(); ++i)
		{
			src.at<uchar>(i->x, i->y) = 0;
		}
		//第二遍循环检测	
		for (int x = 1; x < src.rows - 1; x++)
		{
			for (int y = 1; y < src.cols - 1; y++)
			{
				//白点
				if (src.at<uchar>(x, y) == 1)
				{
					//计算条件一:黑点数2和6之间
					int c1 = 0;
					c1 = src.at<uchar>(x - 1, y - 1) + src.at<uchar>(x, y - 1) + src.at<uchar>(x + 1, y - 1) + src.at<uchar>(x - 1, y) + src.at<uchar>(x + 1, y) + src.at<uchar>(x - 1, y + 1) + src.at<uchar>(x, y + 1) + src.at<uchar>(x + 1, y + 1);
					//c1 = 8 - c1;
					if (c1 >= 2 && c1 <= 6)
					{
						//计算条件二:顺时针0,1个数为1
						int c2 = 0;
						if (src.at<uchar>(x - 1, y - 1) == 0 && src.at<uchar>(x, y - 1) == 1) ++c2;
						if (src.at<uchar>(x, y - 1) == 0 && src.at<uchar>(x + 1, y - 1) == 1) ++c2;
						if (src.at<uchar>(x + 1, y - 1) == 0 && src.at<uchar>(x + 1, y) == 1) ++c2;
						if (src.at<uchar>(x + 1, y) == 0 && src.at<uchar>(x + 1, y + 1) == 1) ++c2;
						if (src.at<uchar>(x + 1, y + 1) == 0 && src.at<uchar>(x, y + 1) == 1) ++c2;
						if (src.at<uchar>(x, y + 1) == 0 && src.at<uchar>(x - 1, y + 1) == 1) ++c2;
						if (src.at<uchar>(x - 1, y + 1) == 0 && src.at<uchar>(x - 1, y) == 1) ++c2;
						if (src.at<uchar>(x - 1, y) == 0 && src.at<uchar>(x - 1, y - 1) == 1) ++c2;
						if (c2 == 1)
						{
							//计算条件三:p2*p4*p8=0
							int c3 = src.at<uchar>(x, y - 1)*src.at<uchar>(x + 1, y)*src.at<uchar>(x - 1, y);
							if (c3 == 0)
							{
								//计算条件四:p2*p6*p8=0
								int c4 = src.at<uchar>(x - 1, y)*src.at<uchar>(x, y - 1)*src.at<uchar>(x, y + 1);
								if (c4 == 0)
								{
									//删掉该点
									//src.at<uchar>(x, y) = 0;
									Point2i p;
									p.x = x;
									p.y = y;
									point1.push_back(p);
									c0++;
								}
							}
						}
					}
				}
			}
		}
		
		for (vector<Point2i>::iterator i = point1.begin(); i != point1.end(); ++i)
		{
			src.at<uchar>(i->x, i->y) = 0;
		}
		//循环,直到没有满足要求的删除点
		if (c0 == 0)
		{
			break;
		}

	}
	//显示细化后图像
	Mat dst = src * 255;//二值转为灰度图显示
	imshow("细化图像", dst);
	//查找交叉点
	Mat src1 = src * 255;
	vector<Point2i> point;
	//{
	int c0 = 0;
	//交叉点检测
	for (int x = 1; x < src1.rows - 1; x++)
	{
		for (int y = 1; y < src1.cols - 1; y++)
		{
			//白点
			if (src1.at<uchar>(x, y) == 255)
			{
				//判断是否为端点:周围只有一个白点连接
				int c1 = 0;
				c1 = src1.at<uchar>(x - 1, y - 1) + src1.at<uchar>(x, y - 1) + src1.at<uchar>(x + 1, y - 1) + src1.at<uchar>(x - 1, y) + src1.at<uchar>(x + 1, y) + src1.at<uchar>(x - 1, y + 1) + src1.at<uchar>(x, y + 1) + src1.at<uchar>(x + 1, y + 1);
				if (c1 == 255)
				{
					//端点
					Point2i p;
					p.x = x;
					p.y = y;
					point.push_back(p);
				}
				//判断是否为交叉点:大于某个阈值
				int c2 = 0;
				if (src1.at<uchar>(x - 1, y - 1) == 0 && src1.at<uchar>(x, y - 1) == 255) ++c2;
				if (src1.at<uchar>(x, y - 1) == 0 && src1.at<uchar>(x + 1, y - 1) == 255) ++c2;
				if (src1.at<uchar>(x + 1, y - 1) == 0 && src1.at<uchar>(x + 1, y) == 255) ++c2;
				if (src1.at<uchar>(x + 1, y) == 0 && src1.at<uchar>(x + 1, y + 1) == 255) ++c2;
				if (src1.at<uchar>(x + 1, y + 1) == 0 && src1.at<uchar>(x, y + 1) == 255) ++c2;
				if (src1.at<uchar>(x, y + 1) == 0 && src1.at<uchar>(x - 1, y + 1) == 255) ++c2;
				if (src1.at<uchar>(x - 1, y + 1) == 0 && src1.at<uchar>(x - 1, y) == 255) ++c2;
				if (src.at<uchar>(x - 1, y) == 0 && src1.at<uchar>(x - 1, y - 1) == 255) ++c2;
				if (c2 >= 3)
				{
					//画交叉点
					Point2i p;
					p.x = x;
					p.y = y;
					point.push_back(p);
				}
			}
		}
	}
	//画交叉点
	for (vector<Point2i>::iterator i = point.begin(); i != point.end(); ++i)
	{
		circle(src1, Point2i(i->y, i->x), 5, Scalar(255));
	}
	//显示细化后图像
	imshow("交叉点图像", src1);
}
//第四次作业
//1、腐蚀膨胀
//图像腐蚀
Mat my_erode()
{
	Mat src = imread("E:/opencv project/homework/week1/data/5.jpg", 0);
	imshow("原图", src);
	threshold(src, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	/*											   
	//显示结构元素
	cout << "结构元素" << endl;
	cout << "0" << "   " << "1" << "   " << "0" << endl;
	cout << "1" << "   " << "1" << "   " << "1" << endl;
	cout << "0" << "   " << "1" << "   " << "0" << endl;
	*/
	//全黑图像
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	vector<Point2i> point1;//腐蚀元素
	for (int x = 1; x < src.rows - 1; x++)
	{
		for (int y = 1; y < src.cols - 1; y++)
		{
			//定义8邻域
			int pixel[9];
			pixel[0] = src.at<uchar>(x - 1, y - 1);
			pixel[1] = src.at<uchar>(x, y - 1);
			pixel[2] = src.at<uchar>(x, y + 1);
			pixel[3] = src.at<uchar>(x - 1, y);
			pixel[4] = src.at<uchar>(x, y);
			pixel[5] = src.at<uchar>(x + 1, y);
			pixel[6] = src.at<uchar>(x - 1, y + 1);
			pixel[7] = src.at<uchar>(x, y + 1);
			pixel[8] = src.at<uchar>(x + 1, y + 1);
			if (pixel[1] && pixel[3] && pixel[4] && pixel[5] && pixel[7])
			{
				Point2i p;
				p.x = x;
				p.y = y;
				point1.push_back(p);
			}
		}
	}
	//腐蚀结果
	for (vector<Point2i>::iterator i = point1.begin(); i != point1.end(); ++i)
	{
		dst.at<uchar>(i->x, i->y) = 1;
	}
	dst = dst * 255;
	
	return dst;
}
//图像膨胀
Mat my_dilate()
{
	Mat src = imread("E:/opencv project/homework/week1/data/5.jpg", 0);
	threshold(src, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	vector<Point2i> point2;//膨胀元素
	for (int x = 1; x < src.rows - 1; x++)
	{
		for (int y = 1; y < src.cols - 1; y++)
		{
			//定义8邻域
			int pixel[9];
			pixel[0] = src.at<uchar>(x - 1, y - 1);
			pixel[1] = src.at<uchar>(x, y - 1);
			pixel[2] = src.at<uchar>(x, y + 1);
			pixel[3] = src.at<uchar>(x - 1, y);
			pixel[4] = src.at<uchar>(x, y);
			pixel[5] = src.at<uchar>(x + 1, y);
			pixel[6] = src.at<uchar>(x - 1, y + 1);
			pixel[7] = src.at<uchar>(x, y + 1);
			pixel[8] = src.at<uchar>(x + 1, y + 1);
			if (pixel[1] && pixel[3] && pixel[4] && pixel[5] && pixel[7])
			{
				Point2i p;
				p.x = x;
				p.y = y;
				point2.push_back(p);
			}
		}
	}
	//膨胀结果
	for (vector<Point2i>::iterator i = point2.begin(); i != point2.end(); ++i)
	{
		dst.at<uchar>(i->x, i->y) = 1;
		dst.at<uchar>(i->x, i->y - 1) = 1;
		dst.at<uchar>(i->x - 1, i->y) = 1;
		dst.at<uchar>(i->x + 1, i->y) = 1;
		dst.at<uchar>(i->x, i->y + 1) = 1;
	}
	dst = dst * 255;
	
	return dst;
}
void week1_qt::fushipengzhang()
{
	//差图
	Mat my_erode();
	Mat dst1 = my_erode();
	imshow("腐蚀图像", dst1);
	Mat my_dilate();
	Mat dst2 = my_dilate();
	imshow("膨胀图像", dst2);
	Mat dst3 = dst2 - dst1;
	imshow("差图", dst3);
	imwrite("20.jpg", dst3);
	//显示结构元素
	ui.textBrowser->insertPlainText(tr("0   1   0\n"));
	ui.textBrowser->insertPlainText(tr("1   1   1\n"));
	ui.textBrowser->insertPlainText(tr("0   1   0\n"));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}
//直线检测
void week1_qt::line_detect()
{
	Mat my_erode();
	Mat dst1 = my_erode();
	Mat my_dilate();
	Mat dst2 = my_dilate();
	Mat src = dst2 - dst1;
	imshow("边缘检测后", src);
	threshold(src, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	int **count;//用于统计个数,θ取值[0到360)
	int lmax = (int)sqrt(src.rows*src.rows + src.cols + src.cols);//距离的最大值
 //初始化极坐标
	count = new int*[359];
	for (int i = 0; i < 359; i++)
	{
		count[i] = new int[lmax];
		memset(count[i], 0, sizeof(int)*lmax);
	}
	//统计count的值
	for (int x = 0; x < src.rows; x++)
	{
		for (int y = 0; y < src.cols; y++)
		{
			if (src.at<uchar>(x, y) == 1)
			{
				//找出对应的所有θ和p值
				for (int theta = 0; theta < 359; theta++)
				{
					int L = (int)((x*cos(theta * CV_PI / 180) + y*sin(theta * CV_PI / 180)));
					if (L > 0 && L < lmax)
					{
						count[theta][L]++;
					}
				}
			}
		}
	}
	//阈值处理
	Point2i **p;//画直线用储存点
				//初始化
	p = new Point2i*[359];
	for (int i = 0; i < 359; i++)
	{
		p[i] = new Point2i[lmax];
		memset(p[i], (0, 0), sizeof(Point2i)*lmax);
	}
	src = 50 * src;
	int th = 80;
	int c = 0;//统计直线个数
	for (int i = 0; i < 359; i++)
	{
		for (int j = 0; j < lmax; j++)
		{
			if (count[i][j]>th)
			{
				//认为检测到一条直线
				c++;
				ui.textBrowser->insertPlainText(tr("Line%1:").arg(c));								ui.textBrowser->insertPlainText(tr("%1\n").arg(count[i][j]));
				ui.textBrowser->moveCursor(QTextCursor::Start);
				//cout << "直线" << c << "的长度为:" << count[i][j];
				//画直线
				for (int x = 0; x < src.rows; x++)
				{
					for (int y = 0; y < src.cols; y++)
					{
						if (src.at<uchar>(x, y) == 50)
						{
							if (j == (int)((x*cos(i * CV_PI / 180) + y*sin(i * CV_PI / 180))))
							{
								Point2i p1;
								p1.x = y;
								p1.y = x;
								if (p[i][j].x == 0 && p[i][j].y == 0)
								{
									p[i][j] = p1;
								}
								else
								{
									Point2i p2;
									p2 = p[i][j];
									line(src, p1, p2, Scalar(255), 1);
								}
							}
						}
					}
				}
			}
		}
	}
	imshow("检测直线", src);
}
//3、应用
Mat my_erode1(Mat src1)//灰度
{
	Mat src;
	threshold(src1, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	vector<Point2i> point1;//腐蚀元素
	for (int x = 1; x < src.rows - 1; x++)
	{
		for (int y = 1; y < src.cols - 1; y++)
		{
			//定义8邻域
			int pixel[9];
			pixel[0] = src.at<uchar>(x - 1, y - 1);
			pixel[1] = src.at<uchar>(x, y - 1);
			pixel[2] = src.at<uchar>(x, y + 1);
			pixel[3] = src.at<uchar>(x - 1, y);
			pixel[4] = src.at<uchar>(x, y);
			pixel[5] = src.at<uchar>(x + 1, y);
			pixel[6] = src.at<uchar>(x - 1, y + 1);
			pixel[7] = src.at<uchar>(x, y + 1);
			pixel[8] = src.at<uchar>(x + 1, y + 1);
			if (pixel[1] && pixel[2] && pixel[3] && pixel[4] && pixel[5] && pixel[6] && pixel[7] && pixel[8] && pixel[9])
			{
				Point2i p;
				p.x = x;
				p.y = y;
				point1.push_back(p);
			}
		}
	}
	//腐蚀结果
	for (vector<Point2i>::iterator i = point1.begin(); i != point1.end(); ++i)
	{
		dst.at<uchar>(i->x, i->y) = 1;
	}
	dst = dst * 255;
	return dst;
}
//图像膨胀
Mat my_dilate1(Mat src1)//灰度
{
	Mat src;
	threshold(src1, src, 140, 1, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	vector<Point2i> point2;//膨胀元素
	for (int x = 1; x < src.rows - 1; x++)
	{
		for (int y = 1; y < src.cols - 1; y++)
		{
			//定义8邻域
			int pixel[9];
			pixel[0] = src.at<uchar>(x - 1, y - 1);
			pixel[1] = src.at<uchar>(x, y - 1);
			pixel[2] = src.at<uchar>(x, y + 1);
			pixel[3] = src.at<uchar>(x - 1, y);
			pixel[4] = src.at<uchar>(x, y);
			pixel[5] = src.at<uchar>(x + 1, y);
			pixel[6] = src.at<uchar>(x - 1, y + 1);
			pixel[7] = src.at<uchar>(x, y + 1);
			pixel[8] = src.at<uchar>(x + 1, y + 1);
			if (pixel[1] && pixel[2] && pixel[3] && pixel[4] && pixel[5] && pixel[6] && pixel[7] && pixel[8] && pixel[9])
			{
				Point2i p;
				p.x = x;
				p.y = y;
				point2.push_back(p);
			}
		}
	}
	//膨胀结果
	for (vector<Point2i>::iterator i = point2.begin(); i != point2.end(); ++i)
	{
		dst.at<uchar>(i->x - 1, i->y - 1) = 1;
		dst.at<uchar>(i->x, i->y - 1) = 1;
		dst.at<uchar>(i->x, i->y + 1) = 1;
		dst.at<uchar>(i->x - 1, i->y) = 1;
		dst.at<uchar>(i->x, i->y) = 1;
		dst.at<uchar>(i->x + 1, i->y) = 1;
		dst.at<uchar>(i->x - 1, i->y + 1) = 1;
		dst.at<uchar>(i->x, i->y + 1) = 1;
		dst.at<uchar>(i->x + 1, i->y + 1) = 1;
	}
	dst = dst * 255;
	return dst;
}
//开运算
Mat kai(Mat src)
{
	//腐蚀
	Mat my_erode1(Mat src);
	Mat dst1 = my_erode1(src);
	//膨胀
	Mat my_dilate1(Mat src);
	Mat dst2 = my_dilate1(dst1);
	//结果显示
	//imshow("开运算结果", dst2);
	return dst2;
}
//闭运算
Mat bi(Mat src)
{
	//膨胀
	Mat my_dilate1(Mat src);
	Mat dst1 = my_dilate1(src);
	//腐蚀
	Mat my_erode1(Mat src);
	Mat dst2 = my_erode1(dst1);
	//结果显示
	//imshow("闭运算结果", dst2);
	return dst2;
}
//形态学滤波
void week1_qt::lvbo()
{
	//读图
	Mat src = imread("E:/opencv project/homework/week1/data/20.png", 0);
	imshow("原图", src);
	//开运算去噪
	Mat kai(Mat src1);
	Mat k = kai(src);
	imshow("开运算结果", k);
	//闭运算修复断裂
	Mat bi(Mat src1);
	Mat b1 = bi(src);
	imshow("闭运算结果", b1);
	Mat b = bi(k);
	//结果显示
	imshow("滤波结果", b);
}
//第五次作业
//1、2、边界线链码及周长面积计算
void week1_qt::lianma()
{
	//读图
	Mat src = imread("E:/opencv project/homework/week1/data/5.jpg", 0);//腐蚀膨胀差图
	threshold(src, src, 140, 255, cv::THRESH_BINARY);//二值化,前景为1,背景为0
	imshow("原图", src);
	//链码图像
	Mat dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	vector<Point2i> bianyuan;
	//步骤一;找b0,c0
	Point2i b0;
	b0.x = 0;
	b0.y = 0;
	for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			if ((src.at<uchar>(i, j) == 255) && (b0.x == 0 && b0.y == 0))
			{
				b0.x = i;
				b0.y = j;
			}
		}
	}
	circle(dst, Point2i(b0.y, b0.x), 5, Scalar(255));
	Point2i c0;
	c0.x = b0.x;
	c0.y = b0.y - 1;
	//迭代点
	Point2i b;
	Point2i c;
	//步骤二:找b1,c1
	Point2i b1;
	Point2i c1;
	b.x = c0.x;
	b.y = c0.y;
	dst.at<uchar>(b.x, b.y) = 255;
	//链码
	vector<int> lianma;
	int ma = 4;
	for (int i = 0; i < 8; i++)
	{
		if (ma == 0)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x + 1;
			b.y = b.y;
			ma = 7;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 1)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x + 1;
			b.y = b.y;
			ma = 0;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 2)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x;
			b.y = b.y + 1;
			ma = 1;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 3)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x;
			b.y = b.y + 1;
			ma = 2;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 4)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x - 1;
			b.y = b.y;
			ma = 3;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 5)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x - 1;
			b.y = b.y;
			ma = 4;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 6)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x;
			b.y = b.y - 1;
			ma = 5;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}
		if (ma == 7)
		{
			c.x = b.x;
			c.y = b.y;
			b.x = b.x;
			b.y = b.y - 1;
			ma = 6;
			if (src.at<uchar>(b.x, b.y) == 255)
			{
				break;
			}
		}

	}
	b1.x = b.x;
	b1.y = b.y;
	c1.x = c.x;
	c1.y = c.y;
	dst.at<uchar>(b.x, b.y) = 255;
	lianma.push_back(ma);
	bianyuan.push_back(b0);
	bianyuan.push_back(b1);
	//步骤三:循环查找
	while (1)//条件
	{
		//初始化新码
		if (c.x == b.x&&c.y == b.y + 1)
		{
			ma = 0;
		}
		if (c.x == b.x - 1 && c.y == b.y + 1)
		{
			ma = 1;
		}
		if (c.x == b.x - 1 && c.y == b.y)
		{
			ma = 2;
		}
		if (c.x == b.x - 1 && c.y == b.y - 1)
		{
			ma = 3;
		}
		if (c.x == b.x&&c.y == b.y - 1)
		{
			ma = 4;
		}
		if (c.x == b.x + 1 && c.y == b.y - 1)
		{
			ma = 5;
		}
		if (c.x == b.x + 1 && c.y == b.y)
		{
			ma = 6;
		}
		if (c.x == b.x + 1 && c.y == b.y + 1)
		{
			ma = 7;
		}
		//新的b,c查找
		b.x = c.x;
		b.y = c.y;
		for (int i = 0; i < 8; i++)
		{
			if (ma == 0)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x + 1;
				b.y = b.y;
				ma = 7;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 1)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x + 1;
				b.y = b.y;
				ma = 0;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 2)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x;
				b.y = b.y + 1;
				ma = 1;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 3)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x;
				b.y = b.y + 1;
				ma = 2;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 4)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x - 1;
				b.y = b.y;
				ma = 3;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 5)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x - 1;
				b.y = b.y;
				ma = 4;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 6)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x;
				b.y = b.y - 1;
				ma = 5;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
			if (ma == 7)
			{
				c.x = b.x;
				c.y = b.y;
				b.x = b.x;
				b.y = b.y - 1;
				ma = 6;
				if (src.at<uchar>(b.x, b.y) == 255)
				{
					break;
				}
				continue;
			}
		}
		lianma.push_back(ma);
		bianyuan.push_back(b);
		dst.at<uchar>(b.x, b.y) = 255;
		if (bianyuan[bianyuan.size() - 1].x == b1.x && bianyuan[bianyuan.size() - 1].y == b1.y&&bianyuan[bianyuan.size() - 2].x == b0.x&&bianyuan[bianyuan.size() - 2].y == b0.y)
		{
			break;
		}
	}
	imshow("边缘图", dst);
	//输出链码
	//cout << "链码为:" << endl;
	for (int k = 0; k < lianma.size(); k++)
	{
		ui.textBrowser->insertPlainText(tr("%1").arg(lianma[k]));
		ui.textBrowser->moveCursor(QTextCursor::Start);
		//cout << lianma[k];
	}
	//cout << endl;
	ui.textBrowser->insertPlainText(tr("lianma:\n"));
	ui.textBrowser->moveCursor(QTextCursor::Start);
	//计算链码长度
	int j = 0;
	int o = 0;
	for (int i = 0; i < lianma.size(); i++)
	{
		if (lianma[i] % 2 == 0)
		{
			o++;
		}
		else
		{
			j++;
		}
	}
	float l = o + 1.414*j;
	//cout << "长度为:" << l << endl;
	ui.textBrowser->insertPlainText(tr("length:%1\n").arg(l));
	ui.textBrowser->moveCursor(QTextCursor::Start);
	//计算区域面积
	int A = 0;
	for (int i = 1; i < bianyuan.size() - 1; i++)//除去最后存入的b1,b0最后测
	{
		int a = lianma[i - 1];//进入该点的链码
		int b = lianma[i];//出该点的链码
		Point2i p;
		p.x = bianyuan[i].x;
		p.y = bianyuan[i].y;
		//判断p是上边界点还是下边界点
		//上边界
		if ((a == 0 && b == 0) || (a == 0 && b == 1) || (a == 0 && b == 6) || (a == 0 && b == 7) || (a == 1 && b == 0) || (a == 1 && b == 1) || (a == 1 && b == 6) || (a == 1 && b == 7) || (a == 2 && b == 0) || (a == 2 && b == 1) || (a == 2 && b == 6) || (a == 2 && b == 7) || (a == 7 && b == 0) || (a == 7 && b == 1) || (a == 7 && b == 6) || (a == 7 && b == 7))
		{
			A = A - p.y;
		}
		//既上又下
		if ((a == 0 && b == 4) || (a == 0 && b == 5) || (a == 1 && b == 5) || (a == 3 && b == 0) || (a == 3 && b == 1) || (a == 3 && b == 7) || (a == 4 && b == 0) || (a == 4 && b == 1) || (a == 5 && b == 1) || (a == 7 && b == 3) || (a == 7 && b == 4) || (a == 7 && b == 5))
		{
			A = A + 1;
		}
		//下边界
		if ((a == 3 && b == 2) || (a == 3 && b == 3) || (a == 3 && b == 4) || (a == 3 && b == 5) || (a == 4 && b == 2) || (a == 4 && b == 3) || (a == 4 && b == 4) || (a == 4 && b == 5) || (a == 5 && b == 2) || (a == 5 && b == 3) || (a == 5 && b == 4) || (a == 5 && b == 5) || (a == 6 && b == 2) || (a == 6 && b == 3) || (a == 6 && b == 4) || (a == 6 && b == 5))
		{
			A = A + p.y + 1;
		}
	}
	//cout << "区域面积:" << A << endl;
	ui.textBrowser->insertPlainText(tr("area:%1\n").arg(A));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}
//3、共生矩阵及特征
void week1_qt::gongsheng()
{
	//灰度图
	Mat src = imread("E:/opencv project/homework/week1/data/13.jpg", 0);
	imshow("原图", src);
	//创建原始共生矩阵
	Mat dst1 = Mat::zeros(256, 256, CV_8UC1);//0
	Mat dst2 = Mat::zeros(256, 256, CV_8UC1);//45
	Mat dst3 = Mat::zeros(256, 256, CV_8UC1);//90
	Mat dst4 = Mat::zeros(256, 256, CV_8UC1);//135
	//统计和
	double n1 = 0;
	double n2 = 0;
	double n3 = 0;
	double n4 = 0;
	//0
	for (int x = 0; x < src.rows - 1; x++)
	{
		for (int y = 0; y < src.cols; y++)
		{
			int a = src.at<uchar>(x, y);
			int b = src.at<uchar>(x + 1, y);
			dst1.at<uchar>(a, b)++;
			n1++;
		}
	}
	imshow("0方向共生矩阵", dst1);
	//45
	for (int x = 1; x < src.rows; x++)
	{
		for (int y = 0; y < src.cols - 1; y++)
		{
			int a = src.at<uchar>(x, y);
			int b = src.at<uchar>(x - 1, y + 1);
			dst2.at<uchar>(a, b)++;
			n2++;
		}
	}
	imshow("45方向共生矩阵", dst2);
	//90
	for (int x = 0; x < src.rows; x++)
	{
		for (int y = 0; y < src.cols - 1; y++)
		{
			int a = src.at<uchar>(x, y);
			int b = src.at<uchar>(x, y + 1);
			dst3.at<uchar>(a, b)++;
			n3++;
		}
	}
	imshow("90方向共生矩阵", dst3);
	//135
	for (int x = 0; x < src.rows - 1; x++)
	{
		for (int y = 0; y < src.cols - 1; y++)
		{
			int a = src.at<uchar>(x, y);
			int b = src.at<uchar>(x + 1, y + 1);
			dst4.at<uchar>(a, b)++;
			n4++;
		}
	}
	imshow("135方向共生矩阵", dst4);
	//计算特征
	//0
	//对比度
	double d1 = 0;
	double d2 = 0;
	double d3 = 0;
	double d4 = 0;
	//同质性
	double t1 = 0;
	double t2 = 0;
	double t3 = 0;
	double t4 = 0;
	//能量
	double e1 = 0;
	double e2 = 0;
	double e3 = 0;
	double e4 = 0;
	//熵
	double s1 = 0;
	double s2 = 0;
	double s3 = 0;
	double s4 = 0;
	//cout << "n:" << n1 << " " << n2 << " " << n3 << " " << n4 << endl;
	for (int i = 0; i < 256; i++)
	{
		for (int j = 0; j < 256; j++)
		{
			//对比度
			d1 = d1 + (i - j)*(i - j)*dst1.at<uchar>(i, j) / n1;
			d2 = d2 + (i - j)*(i - j)*dst2.at<uchar>(i, j) / n2;
			d3 = d3 + (i - j)*(i - j)*dst3.at<uchar>(i, j) / n3;
			d4 = d4 + (i - j)*(i - j)*dst4.at<uchar>(i, j) / n4;
			//同质性
			t1 = t1 + dst1.at<uchar>(i, j) / (n1*(1 + abs(i - j)));
			t2 = t2 + dst2.at<uchar>(i, j) / (n2*(1 + abs(i - j)));
			t3 = t3 + dst3.at<uchar>(i, j) / (n3*(1 + abs(i - j)));
			t4 = t4 + dst4.at<uchar>(i, j) / (n4*(1 + abs(i - j)));
			//能量
			e1 = e1 + (dst1.at<uchar>(i, j) / n1)*(dst1.at<uchar>(i, j) / n1);
			e2 = e2 + (dst2.at<uchar>(i, j) / n2)*(dst2.at<uchar>(i, j) / n2);
			e3 = e3 + (dst3.at<uchar>(i, j) / n3)*(dst3.at<uchar>(i, j) / n3);
			e4 = e4 + (dst4.at<uchar>(i, j) / n4)*(dst4.at<uchar>(i, j) / n4);
			//熵
			if (dst1.at<uchar>(i, j) != 0)
			{
				s1 = s1 - (dst1.at<uchar>(i, j) / n1)*log(dst1.at<uchar>(i, j) / n1) / log(2);
			}
			if (dst2.at<uchar>(i, j) != 0)
			{
				s2 = s2 - (dst2.at<uchar>(i, j) / n2)*log(dst2.at<uchar>(i, j) / n2) / log(2);
			}
			if (dst3.at<uchar>(i, j) != 0)
			{
				s3 = s3 - (dst3.at<uchar>(i, j) / n3)*log(dst3.at<uchar>(i, j) / n3) / log(2);
			}
			if (dst4.at<uchar>(i, j) != 0)
			{
				s4 = s4 - (dst4.at<uchar>(i, j) / n4)*log(dst4.at<uchar>(i, j) / n4) / log(2);
			}
		}
	}
	//cout << "对比度:" << endl;
	//cout << d1 << endl << d2 << endl << d3 << endl << d4 << endl;
	ui.textBrowser->insertPlainText(tr("duibidu:\n"));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(d1));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(d2));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(d3));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(d4));
	ui.textBrowser->moveCursor(QTextCursor::Start);
	//cout << "同质性:" << endl;
	//cout << t1 << endl << t2 << endl << t3 << endl << t4 << endl;
	ui.textBrowser->insertPlainText(tr("tongzhixing:\n"));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(t1));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(t2));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(t3));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(t4));
	ui.textBrowser->moveCursor(QTextCursor::Start);
	//cout << "能量:" << endl;
	//cout << e1 << endl << e2 << endl << e3 << endl << e4 << endl;
	ui.textBrowser->insertPlainText(tr("nengliang:\n"));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(e1));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(e2));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(e3));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(e4));
	ui.textBrowser->moveCursor(QTextCursor::Start);
	//cout << "熵:" << endl;
	//cout << s1 << endl << s2 << endl << s3 << endl << s4 << endl;
	ui.textBrowser->insertPlainText(tr("shang:\n"));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(s1));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(s2));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(s3));
	ui.textBrowser->insertPlainText(tr("%1\n").arg(s4));
	ui.textBrowser->moveCursor(QTextCursor::Start);
}

Qt界面

在这里插入图片描述

发布了26 篇原创文章 · 获赞 0 · 访问量 1206

猜你喜欢

转载自blog.csdn.net/weixin_44264994/article/details/103799574