图像的矩

矩的计算:moments()函数

计算轮廓面积:contourArea()函数



#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include<iostream>
using namespace cv;
using namespace std; //-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main()
{
vector<Point> contour;
contour.push_back(Point2f(0, 0));
contour.push_back(Point2f(10, 0));
contour.push_back(Point2f(10, 10));
contour.push_back(Point2f(5, 4)); double area0 = contourArea(contour);
vector<Point> approx;
approxPolyDP(contour, approx, 5, true);
double area1 = contourArea(approx); cout << "area0=" << area0 << endl << "area1=" << area1 << endl << "approx poly vertices=" << approx.size() << endl;
waitKey(0);
system("pause");
return(0);
}

计算轮廓长度:arcLength()函数



综合实例程序:查找和绘制图像轮廓矩

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std; //-----------------------------------【宏定义部分】--------------------------------------------
// 描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【原始图】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【图像轮廓】" //为窗口标题定义的宏 //-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage; Mat g_grayImage;
int g_nThresh = 100;
int g_nMaxThresh = 255;
RNG g_rng(12345);
Mat g_cannyMat_output;
vector<vector<Point> > g_vContours;
vector<Vec4i> g_vHierarchy; //-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void*);
static void ShowHelpText(); //-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
//【0】改变console字体颜色
system("color 9F"); ShowHelpText();
// 读入原图像, 返回3通道图像数据
g_srcImage = imread("1.jpg", 1); // 把原图像转化成灰度图像并进行平滑
cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
blur(g_grayImage, g_grayImage, Size(3, 3)); // 创建新窗口
namedWindow(WINDOW_NAME1, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME1, g_srcImage); //创建滚动条并进行初始化
createTrackbar(" 阈值", WINDOW_NAME1, &g_nThresh, g_nMaxThresh, on_ThreshChange);
on_ThreshChange(0, 0); waitKey(0);
return(0);
} //-----------------------------------【on_ThreshChange( )函数】-------------------------------
// 描述:回调函数
//-----------------------------------------------------------------------------------------------
void on_ThreshChange(int, void*)
{
// 使用Canndy检测边缘
Canny(g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh * 2, 3); // 找到轮廓
findContours(g_cannyMat_output, 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));
} // 绘制轮廓
Mat drawing = Mat::zeros(g_cannyMat_output.size(), CV_8UC3);
for (unsigned int i = 0; i < g_vContours.size(); i++)
{
Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));//随机生成颜色值
drawContours(drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point());//绘制外层和内层轮廓
circle(drawing, mc[i], 4, color, -1, 8, 0);;//绘制圆
} // 显示到窗口中
namedWindow(WINDOW_NAME2, WINDOW_AUTOSIZE);
imshow(WINDOW_NAME2, drawing); // 通过m00计算轮廓面积并且和OpenCV函数比较
printf("\t 输出内容: 面积和轮廓长度\n");
for (unsigned int i = 0; i < g_vContours.size(); i++)
{
printf(" >通过m00计算出轮廓[%d]的面积: (M_00) = %.2f \n OpenCV函数计算出的面积=%.2f , 长度: %.2f \n\n", i, mu[i].m00, contourArea(g_vContours[i]), arcLength(g_vContours[i], true));
Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
drawContours(drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point());
circle(drawing, mc[i], 4, color, -1, 8, 0);
}
} //-----------------------------------【ShowHelpText( )函数】-----------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
}

分水岭算法



实现分水岭算法:watershed()函数

综合示例程序:分水岭算法

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace std; //-----------------------------------【宏定义部分】--------------------------------------------
// 描述:定义一些辅助宏
//------------------------------------------------------------------------------------------------
#define WINDOW_NAME1 "【程序窗口1】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【分水岭算法效果图】" //为窗口标题定义的宏 //-----------------------------------【全局函变量声明部分】--------------------------------------
// 描述:全局变量的声明
//-----------------------------------------------------------------------------------------------
Mat g_maskImage, g_srcImage;
Point prevPt(-1, -1); //-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数的声明
//-----------------------------------------------------------------------------------------------
static void ShowHelpText();
static void on_Mouse(int event, int x, int y, int flags, void*); //-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
//【0】改变console字体颜色
system("color 6F"); //【0】显示帮助文字
ShowHelpText(); //【1】载入原图并显示,初始化掩膜和灰度图
g_srcImage = imread("1.jpg", 1);
imshow(WINDOW_NAME1, g_srcImage);
Mat srcImage, grayImage;
g_srcImage.copyTo(srcImage);
cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY);
cvtColor(g_maskImage, grayImage, COLOR_GRAY2BGR);
g_maskImage = Scalar::all(0); //【2】设置鼠标回调函数
setMouseCallback(WINDOW_NAME1, on_Mouse, 0); //【3】轮询按键,进行处理
while (1)
{
//获取键值
int c = waitKey(0); //若按键键值为ESC时,退出
if ((char)c == 27)
break; //按键键值为2时,恢复源图
if ((char)c == '2')
{
g_maskImage = Scalar::all(0);
srcImage.copyTo(g_srcImage);
imshow("image", g_srcImage);
} //若检测到按键值为1或者空格,则进行处理
if ((char)c == '1' || (char)c == ' ')
{
//定义一些参数
int i, j, compCount = 0;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy; //寻找轮廓
findContours(g_maskImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); //轮廓为空时的处理
if (contours.empty())
continue; //拷贝掩膜
Mat maskImage(g_maskImage.size(), CV_32S);
maskImage = Scalar::all(0); //循环绘制出轮廓
for (int index = 0; index >= 0; index = hierarchy[index][0], compCount++)
drawContours(maskImage, contours, index, Scalar::all(compCount + 1), -1, 8, hierarchy, INT_MAX); //compCount为零时的处理
if (compCount == 0)
continue; //生成随机颜色
vector<Vec3b> colorTab;
for (i = 0; i < compCount; i++)
{
int b = theRNG().uniform(0, 255);
int g = theRNG().uniform(0, 255);
int r = theRNG().uniform(0, 255); colorTab.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
} //计算处理时间并输出到窗口中
double dTime = (double)getTickCount();
watershed(srcImage, maskImage);
dTime = (double)getTickCount() - dTime;
printf("\t处理时间 = %gms\n", dTime*1000. / getTickFrequency()); //双层循环,将分水岭图像遍历存入watershedImage中
Mat watershedImage(maskImage.size(), CV_8UC3);
for (i = 0; i < maskImage.rows; i++)
for (j = 0; j < maskImage.cols; j++)
{
int index = maskImage.at<int>(i, j);
if (index == -1)
watershedImage.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
else if (index <= 0 || index > compCount)
watershedImage.at<Vec3b>(i, j) = Vec3b(0, 0, 0);
else
watershedImage.at<Vec3b>(i, j) = colorTab[index - 1];
} //混合灰度图和分水岭效果图并显示最终的窗口
watershedImage = watershedImage * 0.5 + grayImage * 0.5;
imshow(WINDOW_NAME2, watershedImage);
}
} return 0;
} //-----------------------------------【onMouse( )函数】---------------------------------------
// 描述:鼠标消息回调函数
//-----------------------------------------------------------------------------------------------
static void on_Mouse(int event, int x, int y, int flags, void*)
{
//处理鼠标不在窗口中的情况
if (x < 0 || x >= g_srcImage.cols || y < 0 || y >= g_srcImage.rows)
return; //处理鼠标左键相关消息
if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))
prevPt = Point(-1, -1);
else if (event == EVENT_LBUTTONDOWN)
prevPt = Point(x, y); //鼠标左键按下并移动,绘制出白色线条
else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
Point pt(x, y);
if (prevPt.x < 0)
prevPt = pt;
line(g_maskImage, prevPt, pt, Scalar::all(255), 5, 8, 0);
line(g_srcImage, prevPt, pt, Scalar::all(255), 5, 8, 0);
prevPt = pt;
imshow(WINDOW_NAME1, g_srcImage);
}
} //-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n"); //输出一些帮助信息
printf("\n\n\n\t欢迎来到【分水岭算法】示例程序~\n\n");
printf("\t请先用鼠标在图片窗口中标记出大致的区域,\n\n\t然后再按键【1】或者【SPACE】启动算法。"
"\n\n\t按键操作说明: \n\n"
"\t\t键盘按键【1】或者【SPACE】- 运行的分水岭分割算法\n"
"\t\t键盘按键【2】- 恢复原始图片\n"
"\t\t键盘按键【ESC】- 退出程序\n\n\n");
}

图像修补





实现图像修补:inpaint()函数



综合示例程序:图像修补

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include <iostream>
using namespace cv;
using namespace std; //-----------------------------------【宏定义部分】--------------------------------------------
// 描述:定义一些辅助宏
//----------------------------------------------------------------------------------------------
#define WINDOW_NAME0 "【原始图参考】" //为窗口标题定义的宏
#define WINDOW_NAME1 "【原始图】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【修补后的效果图】" //为窗口标题定义的宏 //-----------------------------------【全局变量声明部分】--------------------------------------
// 描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat srcImage0, srcImage1, inpaintMask;
Point previousPoint(-1, -1);//原来的点坐标 //-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n"); //输出一些帮助信息
printf("\n\n\n\t欢迎来到【图像修复】示例程序~\n");
printf("\n\t请在进行图像修复操作之前,在【原始图】窗口中进行适量的绘制"
"\n\n\t按键操作说明: \n\n"
"\t\t【鼠标左键】-在图像上绘制白色线条\n\n"
"\t\t键盘按键【ESC】- 退出程序\n\n"
"\t\t键盘按键【1】或【SPACE】-进行图像修复操作 \n\n");
} //-----------------------------------【On_Mouse( )函数】--------------------------------
// 描述:响应鼠标消息的回调函数
//----------------------------------------------------------------------------------------------
static void On_Mouse(int event, int x, int y, int flags, void*)
{
//鼠标左键弹起消息
if (event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON))
previousPoint = Point(-1, -1);
//鼠标左键按下消息
else if (event == EVENT_LBUTTONDOWN)
previousPoint = Point(x, y);
//鼠标按下并移动,进行绘制
else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
Point pt(x, y);
if (previousPoint.x < 0)
previousPoint = pt;
//绘制白色线条
line(inpaintMask, previousPoint, pt, Scalar::all(255), 5, 8, 0);
line(srcImage1, previousPoint, pt, Scalar::all(255), 5, 8, 0);
previousPoint = pt;
imshow(WINDOW_NAME1, srcImage1);
}
} //--------------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
//改变console字体颜色
system("color 2F"); //显示帮助文字
ShowHelpText(); //载入原始图并进行掩膜的初始化
Mat srcImage = imread("1.jpg", -1);
if (!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~! \n"); return false; }
srcImage0 = srcImage.clone();
srcImage1 = srcImage.clone();
inpaintMask = Mat::zeros(srcImage1.size(), CV_8U); //显示原始图参考
imshow(WINDOW_NAME0, srcImage0);
//显示原始图
imshow(WINDOW_NAME1, srcImage1);
//设置鼠标回调消息
setMouseCallback(WINDOW_NAME1, On_Mouse, 0); //轮询按键,根据不同的按键进行处理
while (1)
{
//获取按键键值
char c = (char)waitKey(); //键值为ESC,程序退出
if (c == 27)
break; //键值为2,恢复成原始图像
if (c == '2')
{
inpaintMask = Scalar::all(0);
srcImage.copyTo(srcImage1);
imshow(WINDOW_NAME1, srcImage1);
} //键值为1或者空格,进行图像修补操作
if (c == '1' || c == ' ')
{
Mat inpaintedImage;
inpaint(srcImage1, inpaintMask, inpaintedImage, 3, INPAINT_TELEA);
imshow(WINDOW_NAME2, inpaintedImage);
}
} return 0;
}

opencv 6 图像轮廓与图像分割修复 3 图像的矩,分水岭,图像修补的更多相关文章

  1. opencv 6 图像轮廓与图像分割修复 2 使用多边形将轮廓包围

    使用多边形将轮廓包围 返回外部矩阵边界(boundingRect()函数) 寻找最小包围矩形(minAreaRect()函数) 寻找最小包围圆形(minEnclosingCircle函数) 用椭圆拟合 ...

  2. opencv 6 图像轮廓与图像分割修复 1 查找并绘制轮廓 寻找物体的凸包

    查找并绘制轮廓 寻找轮廓(findContours)函数 绘制轮廓(drawContours()函数) 基础实例程序:轮廓查找 #include <opencv2/opencv.hpp> ...

  3. opencv2.4.13+python2.7学习笔记--OpenCV中的图像处理--图像轮廓

    阅读对象:无要求. 1.代码 ''' OpenCV中的轮廓 轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度.为了更加准确,要使用二值化图像.在寻找轮廓之前,要进行阈值化 ...

  4. Python 图像处理 OpenCV (15):图像轮廓

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  5. OpenCV计算机视觉学习(8)——图像轮廓处理(轮廓绘制,轮廓检索,轮廓填充,轮廓近似)

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...

  6. OpenCV笔记(3)(Canny边缘检测、高斯金字塔、拉普拉斯金字塔、图像轮廓、模板匹配)

    一.Canny边缘检测 Canny边缘检测是一系列方法综合的结果.其中主要包含以下步骤: 1.使用高斯滤波器,平滑图像,滤除噪声. 2.计算图像中每个像素点的梯度强度和方向. 3.应用非极大值抑制(N ...

  7. OpenCV学习笔记(12)——OpenCV中的轮廓

    什么是轮廓 找轮廓.绘制轮廓等 1.什么是轮廓 轮廓可看做将连续的点(连着边界)连在一起的曲线,具有相同的颜色和灰度.轮廓在形态分析和物体的检测和识别中很有用. 为了更加准确,要使用二值化图像.在寻找 ...

  8. OpenCV3入门(十)图像轮廓

    1.图像轮廓 1.1图像轮廓与API函数 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形,相对于边缘,轮廓是连续的,边缘并不全部连续.一般地,获取图像轮廓要经过下面几个步骤: 1)     读取 ...

  9. Opencv中的轮廓(不全)

    1.初识轮廓 为了准确,要使用二值化图像.在寻找轮廓之前,要进行阈值化处理,或者Canny边界检测. 查找轮廓的函数会修改原始图像.如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他 ...

随机推荐

  1. 百万年薪python之路 -- 小数据池和代码块练习

    1.请用代码验证 "alex" 是否在字典的值中? info = {'name':'王刚蛋','hobby':'铁锤','age':'18',...100个键值对} info = ...

  2. 不同的phper该如何区别使用swoole和workerman?

       那么我们该怎样去区别应用swoole和workerman?                workerman workerman纯php写的,swoole是php的c扩展,性能肯定更高,百度.腾 ...

  3. Spring 事务笔记

    代码写着写着就钻进源码了. 概念 InfrastructureProxy 结构代理 百度查了查,这个类还没有解释. 进去看了一下: Interface to be implemented by tra ...

  4. OptimalSolution(1)--递归和动态规划(3)数组和字符串问题

    一.最长递增子序列(LIS) 给定数组arr,返回arr的最长递增子序列.例如,arr={2,1,5,3,6,4,8,9,7},返回的最长递增子序列为{1,3,4,5,8,9} 1.时间复杂度为O(N ...

  5. 设计模式(七)Builder模式

    Builder模式,从这个名字我们可以看出来,这种设计模式就是用于组装具有复杂结构的实例的. 下面还是以一个实例程序来解释这种设计模式,先看实例程序的类图. 这里为了调试方便,只实现其中一个功能Tex ...

  6. django-Views之使用视图渲染模板(五)

    render(<request>,<template_name>,context=-None,content_type=None,status=None,using=None) ...

  7. 小白 Python 爬虫部署 Linux

    前言 前面国庆节的时候写过一个简易的爬虫. <Python 简易爬虫实战> 还没看过的同学可以先看一下,这只爬虫主要用来爬取各个博客平台的阅读量等数据,一直以来都是每天晚上我自己手动在本地 ...

  8. Linux进程组和会话

    Linux的进程相互之间有一定的关系.比如说,在Linux进程基础中,我们看到,每个进程都有父进程,而所有的进程以init进程为根,形成一个树状结构.我们在这里讲解进程组和会话,以便以更加丰富的方式了 ...

  9. Spring Cloud alibaba网关 sentinel zuul 四 限流熔断

    spring cloud alibaba 集成了 他内部开源的 Sentinel 熔断限流框架 Sentinel 介绍 官方网址 随着微服务的流行,服务和服务之间的稳定性变得越来越重要.Sentine ...

  10. 解决移动端touch事件与click冲突的问题

    最简单的办法,就只绑定一个事件不就行了: 第二种,我觉得和第一种也没啥区别.. const Button = document.getElementById("targetButton&qu ...