平时研究图像处理比较多,自然也少不了利用统计学的方法来查看图像的各种信息,最近手头写了一个用鼠标点击4个点,围成一个任意4边形,然后统计这个4边形内的灰度的平均值工具。(其实也不算什么工具,:-D)
实现思想:对一张图片A,建立一个掩膜,即:建立一个和图片大小一样的矩阵,让选择的那4个点内的数字为1,其他地方为0。之后再和图片A矩阵对应相乘,这样会只留下这个4边形内的像素值存在,其他地方的像素值都为0了。然后把这些像素值相加,再求平均就得出最终结果。
语言:c++
环境要求:Opencv(我用的是3.4版本)
自然需要先为vs配置Opencv的环境,这个网上有很多教程:CSDN上面也有很多,回头我可以把一个超详细的链接放到这里,但是估计得先经过别人的同意,已经问过了,等待回复中。
下面贴代码:
#include <opencv2/highgui/highgui.hpp>
#include<opencv2\opencv.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
using namespace cv;
using namespace std;
//--定义几个全局变量,因为下面用到的onMouse没有返回值,所以只能通过全局变量来记录要获取的4个坐标的值。
Point pointCoo[4];
int clickNum = 0;
#define WINDOW "Pic"
void onMouse1(int event, int x, int y, int flag, void*) {
if (event == EVENT_LBUTTONDOWN) {
clickNum++;
switch (clickNum) {
case 1: pointCoo[0] = Point(x, y); break;
case 2: pointCoo[1] = Point(x, y); break;
case 3: pointCoo[2] = Point(x, y); break;
case 4: pointCoo[3] = Point(x, y); break;
default: break;
}
//点击一个坐标显示一次定义的全局变量pointCoo里面的值
for (auto con : pointCoo)
cout << con << endl;
}
}
int avgGray(int(*p), Mat img) {
//读入原图片,并获取长宽
int length = img.rows;
int width = img.cols;
//建立一个全是0的图片掩膜
Mat imgM(length, width, CV_8UC1, Scalar(0));
Point points[1][4];
points[0][0] = Point(p[0], p[1]);
points[0][1] = Point(p[2], p[3]);
points[0][2] = Point(p[4], p[5]);
points[0][3] = Point(p[6], p[7]);
//设定传入点的个数
int npt[] = { 4 };
//将四个点围成的区域像素变为1
const Point *pt[1] = { points[0] };
fillPoly(imgM, pt, npt, 1, Scalar(1));
//将图片与掩膜对应相乘,得到只有区域部分非零的图像
Mat reginImg = img.mul(imgM);
namedWindow("image", WINDOW_AUTOSIZE);
imshow("image", reginImg);
waitKey(1000);
//求出来四边形区域内这些像素值的总和。
Scalar theSum = sum(reginImg);
double theSumDouble = theSum.val[0]; //因为求和后是Scalar类型的数据,是含有一个4维数组的结构体,所以需要转化这个sum为double类型。
int theNum = countNonZero(reginImg); //求出这个四边形区域内有多少个像素值。
int theAvg = theSumDouble / theNum;
return theAvg;
}
int main() {
Mat img = imread("X:/grayTest/QQ截图20180110154638.bmp", 0);
namedWindow(WINDOW, WINDOW_AUTOSIZE);
imshow(WINDOW, img);
//waitKey(0);
pointCoo[3].x = 0;
setMouseCallback(WINDOW, onMouse1);
//这个地方比较乱,因为我还没完全理解setMouseCallback怎么用,只能前面设定好pointCoo[3]中的x为0,然后在这里判断x是否已经被赋
//新值来让图片刷新退出。比较low,忘见谅。
while (int(pointCoo[3].x) == 0) {
waitKey(2000);
}
int points[8] = { pointCoo[0].x, pointCoo[0].y, pointCoo[1].x, pointCoo[1].y,
pointCoo[2].x, pointCoo[2].y, pointCoo[3].x, pointCoo[3].y };
int theAvgGray = avgGray(points, img); //定义theAvgGray来接收算出来的灰度平均值
cout << "该区域的灰度平均值为:" << theAvgGray << endl;
system("pause");
return 0;
}
最后贴个图: