画矩形框实际就是画四条直线,本质就是图像像素访问与操作。所以也有3种方式实现,图像像素访问与操作可以看看本人的这一篇博客记录:[OpenCV访问像素值方法]。
注意:如果图片是灰度图,也就是单通道的,会先把它转成三通道的,也就是BGR图。
参数解释:
void draw_box_arr(Mat& image, Point p1, Point p2, int color[3], int width)
{
if (image.channels() == 1)
{
cvtColor(image, image, COLOR_GRAY2BGR);
}
for (int h = p1.x; h <= p1.x + width; ++h)
{
for (int w = p1.y; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p1.x+width; h <= p2.x-width; ++h)
{
for (int w = p1.y; w < p1.y+width; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p2.x-width; h <= p2.x ; ++h)
{
for (int w = p1.y; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p1.x+width; h <= p2.x - width; ++h)
{
for (int w = p2.y-width; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
}
测试时分别使用了自己写的draw_box函数和OpenCV提供的rectangle函数来画矩形框,这里介绍一个OpenCV中测试代码运行实践的方法:
cv::int64 getTickCount()
cv::double getTickFrequency()
//使用方法
double t = (double)getTickCount();
// do something ...
t = ((double)getTickCount() - t)/getTickFrequency();
最后t的值就是do sth运行的时间。
测试代码:
//draw_box_arr_test
double start = (double)getTickCount();
draw_box_arr(input_image, Point(40, 40), Point(200, 200), color, 1);
double t = (getTickCount() - start) / getTickFrequency();
//opencv_rectangle_test
double start1 = (double)getTickCount();
rectangle(input_image, Point(50,50), Point(210,210), Scalar(30, 255, 30), 1, 8, 0);
double t1 = (getTickCount() - start1) / getTickFrequency();
可以看得出来,消耗时间差距还是很明显的。
draw_label()函数主要是添加一个指定颜色的背景,这样在图片中标注出来更方便观察。
void draw_label(Mat& image, Point p, int color[3],String s)
{
//lable size:30 x slen*20+5
int l_w = s.length() * 20 + 5;
int l_h = 30;
for (int h = p.x - l_h; h < p.x; h++)
{
uchar* current_row = image.ptr<uchar>(h);
int x = p.y;
while (x--!=0)
{
current_row++;
current_row++;
current_row++;
}
for (int w = p.y; w < p.y + l_w; w++)
{
*current_row++ = color[0];
*current_row++ = color[1];
*current_row++ = color[2];
}
}
putText(image, s, Point(p.x + 5, p.y - 5), 2, 1, (0, 0, 0), 1, 8);
}
测试代码:
draw_label(input_image,Point(150, 150), color,"asdadasdas");
完整代码:
#include
#include
using namespace cv;
using namespace std;
void draw_box_arr(Mat& image, Point p1, Point p2, int color[3], int width);
void draw_label(Mat& image, Point p1, int color[3],String s);
int main(int argc, char**argv)
{
Mat input_image = imread("./whisper.jpg", 1);
if (input_image.empty())
{
cout << "read input error!" << endl;
return -1;
}
Point p1(90, 150);
Point p2(250, 350);
int color[3] = { 0,255,0 };
draw_label(input_image,p1, color,"flower");
draw_box_arr(input_image, p1, p2, color, 2);
cv::imshow("result", input_image);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}
void draw_box_arr(Mat& image, Point p1, Point p2, int color[3], int width)
{
if (image.channels() == 1)
{
cvtColor(image, image, COLOR_GRAY2BGR);
}
for (int h = p1.x; h <= p1.x + width; ++h)
{
for (int w = p1.y; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p1.x+width; h <= p2.x-width; ++h)
{
for (int w = p1.y; w < p1.y+width; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p2.x-width; h <= p2.x ; ++h)
{
for (int w = p1.y; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
for (int h = p1.x+width; h <= p2.x - width; ++h)
{
for (int w = p2.y-width; w < p2.y; ++w)
{
Vec3b bgr = image.at<Vec3b>(h, w);
bgr[0] = color[0];//b
bgr[1] = color[1];//g
bgr[2] = color[2];//r
image.at<Vec3b>(h, w) = bgr;
}
}
}
void draw_label(Mat& image, Point p, int color[3],String s)
{
//lable size:30 x slen*20+5
int l_w = s.length() * 20 + 5;
int l_h = 30;
for (int h = p.x - l_h; h < p.x; h++)
{
uchar* current_row = image.ptr<uchar>(h);
int x = p.y;
while (x--!=0)
{
current_row++;
current_row++;
current_row++;
}
for (int w = p.y; w < p.y + l_w; w++)
{
*current_row++ = color[0];
*current_row++ = color[1];
*current_row++ = color[2];
}
}
putText(image, s, Point(p.y+5,p.x-5), 2, 1, (0, 0, 0), 1, 4);
}