机器视觉公选课结课实验报告——OpneCv实现简单的图像操作

一.读图像、显示图像、保存图像。imread( );imshow( ); imwrite( ) 函数实现。

代码如下:

//图像的读取,保存,显示,二值化,灰度图

#include<iostream>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\imgproc\types_c.h>
using namespace std;
using namespace cv;
int main(
) {
	Mat img, imgGray, result;
	img = imread("D:\\opencv\\scy.jpg");
	if (!img.data)
	{
		cout << "Please input image path" << endl;
		return 0;
	}	imshow("原图", img);
	cvtColor(img, imgGray, CV_BGR2GRAY);
	imshow("灰度图", imgGray);//灰度图
	blur(imgGray, imgGray, Size(3, 3));
	threshold(imgGray, result, 100, 255, CV_THRESH_BINARY);//对图像进行二值化
	imshow("二值化后的图", result);
	imwrite("二值化的向日葵.jpg", result);//图片保存到文件夹下
	cout << "图片已保存" << endl;
	waitKey();
	return 0;

}

运行结果:

注意内容:

1.其中图像内容被保存到程序所在的文件夹下,即:D:\\opencv\\scy.jpg路径下。

2. 使用标识符CV_BGR2GRAY必须引入头文件:

#include <opencv2\imgproc\types_c.h>

二.(1)图像平滑 Blur( ) ;

代码片段如下:

	//blur的作用是对输入的图像src进行均值滤波后用dst输出
	Mat src, dst;
	src = imread("D:\\opencv\\scy.jpg");
	if (!src.data)
	{
		return 0;
	}
	blur(src, dst, Size(3, 3));//Size(3,3)就表示3x3的核大小

	imshow("原图", src);
	imshow("3×3均值滤波图像输出", dst);
	blur(src, dst, Size(8, 8));//Size(8,8)就表示8x8的核大小
	imshow("8×8均值滤波图像输出", dst);

运行结果:

注意事项:

1.图片路径需要修改为自己的图片路径

2.核大小的值不同时,显示出的图像会有较大的区别,一般来说数值越大,图像越是迷糊。可从运行结果观察。

二(2)高斯平滑GaussianBlur();

代码如下:

#include <opencv2/opencv.hpp>
void example(const cv::Mat& image) {
	cv::namedWindow("Example_in", cv::WINDOW_AUTOSIZE);
	cv::namedWindow("Example_out", cv::WINDOW_AUTOSIZE);
	cv::imshow("Example_in", image);
	cv::Mat out;
	cv::GaussianBlur(image, out, cv::Size(5, 5), 3, 3);
	//cv::GaussianBlur(out, out, cv::Size(5,5), 3, 3);
	cv::imshow("Example_out", out);
	cv::waitKey(0);
}

int main() {
	cv::Mat image = cv::imread("D:\\opencv\\scy.jpg");
	example(image);
	return 0;
}

运行结果:

注意事项:

1.可以对代码中cv::size(5,5)进行修改,但值得注意的是:该数值必须为奇数,当数值都为1时,原图像不发生改变,相应的随着数值的增大,模糊程度增加。

2.图片路径修改为自己的项目下图片的路径。

三.二值化、自适应二值化 threshold(); adaptiveThreshold() ;(主要是adaptiveThreshold() ;threshold();部分见一.)

代码如下:

//自适应阈值实现图像的二值化  adaptiveThreshold()


#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/imgproc/types_c.h>
int main()
{
	cv::Mat srcImage = cv::imread("D:\\opencv\\scy.jpg");
	if (!srcImage.data)
	return 1;
	// 灰度转换
	cv::Mat srcGray;
cv::cvtColor(srcImage, srcGray, CV_RGB2GRAY);//自适应阈值实现图像的二值化
	//cv::imshow("srcGray", srcGray);
cv::Mat dstImage;
// 初始化自适应阈值参数
int blockSize = 5;
int constValue = 10;
const int maxVal = 255;


   //以下是自适应阈值操作
	int adaptiveMethod = 0;
	int thresholdType = 1;
	cv::adaptiveThreshold(srcGray, dstImage,
	maxVal, adaptiveMethod,
	thresholdType, blockSize,
	constValue);
	cv::imshow("dstImage", dstImage);
	cv::waitKey(0);
	return 0;

}

运行结果:

注意事项:

1.图片路径修改为自己项目下的图片文件的路径

四.标记、计算目标的形状特征参数: findContours() 每一个目标的面积、周长、长径、短径(最小外接矩形的长和宽,最小外接椭圆的长径、短径)  

代码如下:

//标记、计算目标的形状特征参数:
//findContours()
//每一个目标的面积、周长、长径、短径(最小外接矩形的长和宽,最小外接椭圆的长径、短径)


#include <opencv2/opencv.hpp>
#include <iostream>
#include "windows.h"
#include <stdio.h>
#include <time.h>
#include <math.h>  
//#include "My_ImageProssing_base.h"
#define WINDOW_NAME "【程序窗口】"			//为窗口标题定义的宏
using namespace cv;
using namespace std;
RNG g_rng(12345);

int main()
{
	//改变控制台字体颜色
	system("color 04");

	//读取图像
	Mat src_image = imread("D:\\opencv\\scy1.jpg", 1);
	//出错判断
	if (!src_image.data)
	{
		cout << "src image load failed!" << endl;
		return -1;
	}
	//显示原图
	namedWindow("原图", WINDOW_NORMAL);
	imshow("原图", src_image);

	//高斯滤波去噪声
	Mat blur_image;
	GaussianBlur(src_image, blur_image, Size(3, 3), 0, 0);
	imshow("GaussianBlur", blur_image);

	//灰度变换与二值化
	Mat gray_image, binary_image;
	cvtColor(blur_image, gray_image, COLOR_BGR2GRAY);
	threshold(gray_image, binary_image, 100, 255, THRESH_BINARY);
	imshow("binary", binary_image);

	//形态学闭操作(粘合断开的区域)
	Mat morph_image;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
	morphologyEx(binary_image, morph_image, MORPH_CLOSE, kernel, Point(-1, -1), 1);
	imshow("morphology", morph_image);

	//查找所有外轮廓
	vector< vector<Point> > contours;
	vector<Vec4i> hireachy;
	findContours(binary_image, contours, hireachy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());

	//定义结果图
	Mat result_image = Mat::zeros(src_image.size(), CV_8UC3);

	//drawContours(result_image, contours, -1, Scalar(0, 0, 255), 1, 8, hireachy);//画出所有轮廓

	//初始化周长、面积、圆形度、周径比
	double len = 0, area = 0, roundness = 0, lenratio = 0;
	float rectangularity;

	//循环找出所有符合条件的轮廓
	for (size_t t = 0; t < contours.size(); t++)
	{
		Scalar color = Scalar(g_rng.uniform(0, 255),
			g_rng.uniform(0, 255), g_rng.uniform(0, 255));//任意值
		//条件:过滤掉小的干扰轮廓
		Rect rect = boundingRect(contours[t]);		//垂直边界最小矩形
		if (rect.width < 10)
			continue;
		//画出找到的轮廓
		drawContours(result_image, contours, t, color, 1, 8, hireachy);

		//绘制轮廓的最小外结矩形
		RotatedRect minrect = minAreaRect(contours[t]);	//最小外接矩形
		int minrectmianji = minrect.size.height * minrect.size.width;
		Point2f P[4];			//四个顶点坐标
		minrect.points(P);
		for (int j = 0; j <= 3; j++)
		{
			line(result_image, P[j], P[(j + 1) % 4], color, 1);
		}
		cout << "最小外接矩形尺寸" << minrect.size << endl;//最小外接矩形尺寸
		cout << "最小外接矩形面积" << minrectmianji << endl;//最小外接矩形尺寸

		//绘制轮廓的最小外结圆
		Point2f center; float radius;
		minEnclosingCircle(contours[t], center, radius);		//最小外接圆
		circle(result_image, center, radius, color, 1);

		//计算面积、周长、圆形度、周径比
		area = contourArea(contours[t]);//计算轮廓面积
		len = arcLength(contours[t], true);//计算轮廓周长
		roundness = (4 * CV_PI * area) / (len * len);//圆形度
		if (minrectmianji == 0)rectangularity = 0;
		else rectangularity = area / minrectmianji;
		//周径比,这里的周即周长,径是指上面找到的轮廓最小外接矩形的长的一条边
		lenratio = len / (minrect.size.height > minrect.size.width ? minrect.size.height : minrect.size.width);

		//输出结果
		cout << "轮廓" << t << ":" << endl;
		cout << "周长:" << len << endl;
		cout << "面积:" << area << endl;
		cout << "圆形度:" << roundness << endl;
		cout << "矩形度:" << rectangularity << endl;
		cout << "周径比:" << lenratio << endl;

	}
	//显示结果
	namedWindow("轮廓图", WINDOW_NORMAL);
	imshow("轮廓图", result_image);

	waitKey(0);
	return 0;
}

运行结果:

 

 

 

注意事项:

1.实现该部分的内容时,最好采用的图片能够有明确的个数,易于功能的实现即目标的数量和大小轮廓的统计。

2.代码中存在自动过滤对于结果有影响的无关紧要的图形部分,因此在选取图像的时候还是要正确合理选择图像。

3.修改图片路径。

五.对测量得到的数据进行统计分析 统计每个参数范围内目标的个数,得到统计直方图。

代码如下:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

int main() {
	Mat src = imread("D:/opencv/scy.jpg");
	if (src.empty())
	{
		cout << "open no success!" << endl;
		return -1;
	}
	imshow("原图", src);
	vector<Mat> dst_num;//建立单通道数组
	split(src, dst_num);//将多通道图片分解成单通道图片
	int histsize = 256;//直方图分级数
	float range[] = { 0, 256 };//像素范围
	const float* histRange = { range };//范围指针
	Mat b_hist, g_hist, r_hist;//建立分量直方图
	//进行直方图提取
	calcHist(&dst_num[0], 1, 0, Mat(), b_hist, 1, &histsize, &histRange, true, false);
	calcHist(&dst_num[1], 1, 0, Mat(), g_hist, 1, &histsize, &histRange);
	calcHist(&dst_num[2], 1, 0, Mat(), r_hist, 1, &histsize, &histRange);
	//通过图片进行显示,直方图提取出来是单通道数组形式
	int hist_w = 512;
	int hist_h = 400;
	int bin_w = hist_w / histsize;
	Mat hist_image(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
	normalize(b_hist, b_hist, 0, hist_h, NORM_MINMAX);
	normalize(g_hist, g_hist, 0, hist_h, NORM_MINMAX);
	normalize(r_hist, r_hist, 0, hist_h, NORM_MINMAX);
	for (int i = 1; i < histsize; i++)
	{
		line(hist_image, Point((i - 1) * bin_w, hist_h - cvRound(b_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2);
		line(hist_image, Point((i - 1) * bin_w, hist_h - cvRound(g_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2);
		line(hist_image, Point((i - 1) * bin_w, hist_h - cvRound(r_hist.at<float>(i - 1))), Point((i)*bin_w, hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2);
	}
	cout << b_hist.at<float>(25) << endl;
	imshow("直方图", hist_image);
	waitKey(0);
	return 0;
}

运行结果:

 

 

注意事项:

1.该部分实现的是简单的RGB图像三通道简单直方图的显示。

2.对于上述我所使用的图像不利于个数的统计,因此数值可能存在误差。

3.更换图片路径为自己的图片路径。


1.该文章作为本人公选课结课报告,有些内容的代码来源于网络,时间已久,如有原创代码作者,请与我联系沟通。

2.作为一个小白,对于opencv的认知仅仅局限于一个狭隘的范围,如有做的不正确的地方,还请各位指正。

3.e-mail:songchengyang@stu.ouc.edu.cn

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值