为了给一张图片加坐标轴,调用openCV,用了两天的时间写了个简化版的版本,直到我看到了这个:
点击打开链接 以及这个:http://answers.opencv.org/question/73233/how-do-you-plot-graphs-in-opencv-projects/
好吧,两天写的其实没什么用。
为了给一张伪彩图上面加坐标轴,我首先参考了:https://blog.csdn.net/xiaoxiaodongshige/article/details/48134895,实现的功能类似于MATLAB的plot功能,我的程序也是根据这个改编的,在XY轴坐标下画曲线。但是,我是要给一张完整的图片加坐标轴,所以相对而言,要简单些,然后就做了一个简单的类,四个函数包括:1.加载内图及规定大小的外框图;2.添加X轴;3.添加Y轴;4.添加标题。
本程序是在MFC里面调openCV作的图,所以还要涉及如何将Mat显示在MFC里面直接显示的问题。请参考:https://blog.csdn.net/ylj135cool/article/details/45933361,中的第一种方法,很好用的。以下是写的源代码:
CPlot_myy.h
#pragma once #include <opencv2\opencv.hpp> #include <cmath> #include <stdio.h> #include <stdlib.h> #include <iostream> #include <vector> #include <math.h> using namespace cv; using namespace std; class CPlot_myy { public: Mat imginside; //传入的中间的伪彩图 Mat imgoutside;//整个外框 //int window_height; //总窗口大小,高 //int window_width; //总窗口大小,宽 int instartcols;//经计算得的内图像宽开始处 int instartrows;//经计算得的内图像高开始处 //CvScalar backgroud_color;//背景颜色,未更改 //CvScalar axis_color;//坐标轴颜色 //CvScalar text_color;//字体颜色 //double y_max;//最大值 //double y_min;//最小值 //double y_number;//数字个数 //double x_max; //double x_min; //double x_number; ////边界大小 //int border_size; void Inputfigure(Mat insidefigure, Mat outerframe);//把图片及外框大小加载进入大图片,并在大框中放置图片 void xlabel(string xlabel_name, CvScalar label_color, double x_max, double x_min, const int x_number);//添加x轴 void ylabel(string ylabel_name, CvScalar label_color, double y_max, double y_min, const int y_number);//添加y轴 //清空图片上的数据 //void clear(); void title(string title_name, CvScalar title_color = Scalar(0, 0, 0));//添加标题 CPlot_myy(); ~CPlot_myy(); };
CPlot_myy.cpp
#include "stdafx.h" #include "Plot_myy.h" #include <sstream> CPlot_myy::CPlot_myy() { } CPlot_myy::~CPlot_myy() { } void CPlot_myy::Inputfigure(Mat insidefigure, Mat outerframe) { this->imginside = insidefigure; this->imgoutside = outerframe; this->instartcols = outerframe.cols - insidefigure.cols - 10; this->instartrows = outerframe.rows - insidefigure.rows - 50; for (int i = 0; i < insidefigure.rows; i++) { for (int j = 0; j < insidefigure.cols; j++) { this->imgoutside.at<Vec3b>(i+ instartrows,j+instartcols)= this->imginside.at<Vec3b>(i,j); } } } void CPlot_myy::ylabel(string ylabel_name, CvScalar label_color, double y_max, double y_min, const int y_number) { line(this->imgoutside, Point(this->instartcols - 1,this->instartrows - 1 ), Point( this->instartcols - 1,this->instartrows + this->imginside.rows ), label_color, 1, 8, 0); line(this->imgoutside, Point(this->instartcols + this->imginside.cols ,this->instartrows - 1), Point(this->instartcols + this->imginside.cols , this->instartrows + this->imginside.rows ), Scalar(0, 0, 0), 1, 8, 0); int ylabel_step = this->imginside.rows / y_number; for (int y = 0; y <= y_number; y++) { double y_jhj = double(y*ylabel_step) / double(this->imginside.rows)*(y_max - y_min) + y_min; char str[20]; sprintf_s(str, 19,"%.0lf", y_jhj); string result = str; line(this->imgoutside, Point(this->instartcols - 10, this->instartrows + this->imginside.rows - y*ylabel_step), Point(this->instartcols - 1, this->instartrows + this->imginside.rows - y*ylabel_step), label_color, 1, 8, 0); putText(this->imgoutside, result, Point(this->instartcols - 30, this->instartrows + this->imginside.rows - y*ylabel_step +3), CV_FONT_HERSHEY_SIMPLEX, 0.3, label_color, 1, 8); } int baseline; Size text_size = cv::getTextSize(ylabel_name, CV_FONT_HERSHEY_SIMPLEX, 1, 8, &baseline); Mat TextSizeframe = Mat(text_size.height + 5, text_size.width/2, CV_8UC3, Scalar(255, 255, 255)); putText(TextSizeframe, ylabel_name, Point(0, text_size.height-1), CV_FONT_HERSHEY_SIMPLEX, 0.5, label_color, 1, 8); /////////////////////////////// //cvNamedWindow("hello", 1); //imshow("hello", TextSizeframe); //cvWaitKey(0); /////////////////////////////// Mat TextSizeframe1, TextSizeframe2; transpose(TextSizeframe, TextSizeframe2); //transpose(TextSizeframe2, TextSizeframe1); flip(TextSizeframe2, TextSizeframe1, 0); for (int i = 0; i < TextSizeframe1.rows; i++) { for (int j = 0; j < TextSizeframe1.cols; j++) { this->imgoutside.at<Vec3b>(i + instartrows + this->imginside.rows/2 - 80, j + instartcols -60) = TextSizeframe1.at<Vec3b>(i, j); } } } void CPlot_myy::xlabel(string xlabel_name, CvScalar label_color, double x_max, double x_min, const int x_number) { line(this->imgoutside, Point(this->instartcols - 1, this->instartrows - 1), Point(this->instartcols + this->imginside.cols , this->instartrows - 1), Scalar(0, 0, 0), 1, 8, 0); line(this->imgoutside, Point(this->instartcols - 1, this->instartrows + this->imginside.rows ), Point(this->instartcols + this->imginside.cols , this->instartrows + this->imginside.rows ), label_color, 1, 8, 0); int xlabel_step = this->imginside.cols / x_number; for (int x = 0; x <= x_number; x++) { double x_jhj = double(x*xlabel_step) / double(this->imginside.cols)*(x_max - x_min) + x_min; char str[20]; sprintf_s(str, 19, "%.0lf", x_jhj); string result = str; line(this->imgoutside, Point(this->instartcols + x*xlabel_step, this->instartrows + this->imginside.rows), Point(this->instartcols + x*xlabel_step, this->instartrows + this->imginside.rows +10), label_color, 1, 8, 0); putText(this->imgoutside, result, Point(this->instartcols + x*xlabel_step-10, this->instartrows + this->imginside.rows +20), CV_FONT_HERSHEY_SIMPLEX, 0.3, label_color, 1, 8); } putText(this->imgoutside, xlabel_name, Point(this->instartcols + this->imginside.cols/2, this->instartrows + this->imginside.rows + 40), CV_FONT_HERSHEY_SIMPLEX, 0.5, label_color, 1, 8); } void CPlot_myy::title(string title_name, CvScalar title_color) { putText(this->imgoutside, title_name, Point(this->instartcols + this->imginside.cols / 2 -200, this->instartrows - 20), CV_FONT_HERSHEY_SIMPLEX, 1, title_color, 1, 8); }
调用方法:
Mat img = imread("E:\\Files\\花.jpg"); Mat dst; boxFilter(img, dst, IPL_DEPTH_8U, Size(3, 3), Point(-1, -1), true, BORDER_DEFAULT); //applyColorMap(myMat, im_color, COLORMAP_JET);//相当好的伪彩图语句? Mat kuangjia =Mat(dst.rows+100, dst.cols+70, CV_8UC3, Scalar(255,255,255)); CPlot_myy outputplot; outputplot.Inputfigure(dst, kuangjia); string yylabel = "Height"; string xxlabel = "Width"; string ttitle_name = "Temperature and strain"; outputplot.ylabel(yylabel, Scalar(0, 0, 0),500,0,10); outputplot.xlabel(xxlabel, Scalar(0, 0, 0), 500, 0, 10); outputplot.title(ttitle_name); //imshow("view", outputplot.imgoutside);//显示图像 imshow("view", kuangjia);
结果,原图:
效果图:
有以下几点说明:
(1)程序先执行以下函数,才规定了Mat的大小,然后再添加X轴,Y轴和标题。
Inputfigure(Mat insidefigure, Mat outerframe)
(2)程序需要根据XY轴及标题大小调整函数的值,才能使标题居中。
(3)类没掌握好,构造析构均没用,应该有Bug。
(4)https://blog.csdn.net/xiaoxiaodongshige/article/details/48134895,与其不同的是,我采用Mat格式,而没有采用IplImage* Figure,