// exercise8.3使用鼠标选择矩形区域并绘制颜色直方图.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//2022年5月16日15:29:56复制过来的代码有时无法运行,需要重新生成解决方案。
#include<opencv.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void on_mouse(int event, int x, int y, int flags, void *para);
Point pt1 = Point(0, 0);
Point pt2 = Point(400, 400);
int main()
{
Mat img = imread("d:\\img\\R-C.jpg");
if (img.empty()) {
cout << "imread failed" << endl;
return -1;
}
imshow("img", img);
setMouseCallback("img", on_mouse, &img);//这里输入一个地址
waitKey();
return 0;
}
void on_mouse(int event, int x, int y, int flags, void *para)//para 是地址
{
Mat & img = *(cv::Mat *)para;//需要指定Mat类型的指针!!!!
Mat mask = cv::Mat::zeros(img.size(), CV_8UC1);
if (event == EVENT_LBUTTONDOWN) {//注意!表示相等需要使用两个等号。
pt1 = Point(x, y);
}
if (event == EVENT_LBUTTONUP) {
pt2 = Point(x, y);
rectangle(mask, Rect(pt1, pt2), Scalar(255), -1);
//1.compute the b_histogram
int bins_b = 32;//每个维度区间的个数
int hist_size_b[] = { bins_b };
float b_range[] = { 0,256 };
const float*ranges_b[] = { b_range };
MatND b_hist;
int channels_b[] = { 0 };
calcHist(&img, 1, channels_b, mask,
b_hist, 1, hist_size_b, ranges_b);//最后一个参数,float类型
//1.draw our b_histogram
double max_val_b;
minMaxLoc(b_hist, 0, &max_val_b, 0, 0);//
int scale_b = b_range[1] / bins_b;
int hist_height_b = 256;
Mat b_hist_img = Mat::zeros(hist_height_b, bins_b*scale_b, CV_8UC3);//创建矩阵
for (int i = 0; i < bins_b; i++)
{
float bin_val = b_hist.at<float>(i);
int intensity = cvRound(bin_val / max_val_b * hist_height_b);
rectangle(b_hist_img, Point(i*scale_b, hist_height_b - 1), Point((i + 1)*scale_b - 1, hist_height_b - intensity), CV_RGB(0, 0, 255),-1);//把线条粗细的参数设置为-1就可以得到实心矩形
}
//2.compute the histogram
int bins_g = 32;//每个维度区间的个数
int hist_size_g[] = { bins_g };
float g_range[] = { 0,256 };
const float*ranges_g[] = { g_range };
MatND g_hist;
int channels_g[] = { 1 };
calcHist(&img, 1, channels_g, mask,
g_hist, 1, hist_size_g, ranges_g);//最后一个参数,float类型
//2.draw our histogram
double max_val_g;
minMaxLoc(g_hist, 0, &max_val_g, 0, 0);//
int scale_g = g_range[1] / bins_g;
int hist_height_g = 256;
Mat g_hist_img = Mat::zeros(hist_height_g, bins_g*scale_g, CV_8UC3);//创建矩阵
for (int i = 0; i < bins_g; i++)
{
float bin_val = g_hist.at<float>(i);
int intensity = cvRound(bin_val / max_val_g * hist_height_g);
rectangle(g_hist_img, Point(i*scale_g, hist_height_g - 1), Point((i + 1)*scale_g - 1, hist_height_g - intensity), CV_RGB(0, 255, 0),-1);//把线条粗细的参数设置为-1就可以得到实心矩形
}
//3.compute the histogram
int bins_r = 32;//每个维度区间的个数
int hist_size_r[] = { bins_r };
float r_range[] = { 0,256 };
const float*ranges_r[] = { r_range };
MatND r_hist;
int channels_r[] = { 2 };
calcHist(&img, 1, channels_r, mask,
r_hist, 1, hist_size_r, ranges_r);//最后一个参数,float类型
//3.draw our histogram
double max_val_r;
minMaxLoc(r_hist, 0, &max_val_r, 0, 0);//
int scale_r = r_range[1] / bins_r;
int hist_height_r = 256;
Mat r_hist_img = Mat::zeros(hist_height_r, bins_r*scale_r, CV_8UC3);//创建矩阵
for (int i = 0; i < bins_r; i++)
{
float bin_val = r_hist.at<float>(i);
int intensity = cvRound(bin_val / max_val_r * hist_height_r);
rectangle(r_hist_img, Point(i*scale_r, hist_height_r - 1), Point((i + 1)*scale_r - 1, hist_height_r - intensity), CV_RGB(255, 0, 0),-1);//把线条粗细的参数设置为-1就可以得到实心矩形
}
//putText(img, text, st_point, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));//在图片上显示坐标点和RGB像素值
rectangle(img, pt1, pt2, cv::Scalar(0,0,0));
imshow("img", img);
imshow("b_histogram", b_hist_img);
imshow("g_histogram", g_hist_img);
imshow("r_histogram", r_hist_img);
waitKey();
}
}