C++ 图像处理库【CImg】配置以及简单使用

17 篇文章 2 订阅
8 篇文章 1 订阅

1. CImg的配置

  • 下载CImg的包到指定的文件夹下,解压
  • 然后只需要在编写的cpp或hpp文件中加入
#include "XX/CImg.h" // XX/是指CImg所在的路径
using namespace cimg_library;

  • 编译命令(环境为windows下的MinGW
g++ -o HelloWorld.exe HelloWorld.cpp -O2 -lgdi32

2.简单使用

1. 读入1.bmp 文件

CImg<unsigned char> SrcImg;
SrcImg.load_bmp("1.bmp");

2. 用CImg.display() 显示

void test_display(CImg<unsigned char> SrcImg) {
	SrcImg.display("work1");
}

这里写图片描述

3. 把1.bmp文件的白色区域变成红色,黑色区域变成绿色

void test_change(CImg<unsigned char> SrcImg) {
	CImg<unsigned char> Img = SrcImg;
	cimg_forXY(Img, x, y) {
		if (Img(x,y,0) == 255 && Img(x,y,1) == 255 && Img(x,y,2) == 255) {
			Img(x,y,0) = 255;
			Img(x,y,1) = 0;
			Img(x,y,2) = 0;
 		}
	}
	cimg_forXY(Img, x, y) {
		if (Img(x,y,0) == 0 && Img(x,y,1) == 0 && Img(x,y,2) == 0) {
			Img(x,y,0) = 0;
			Img(x,y,1) = 255;
			Img(x,y,2) = 0;
 		}
	}
	Img.display("work2");
}

这里写图片描述

4. 在图上绘制一个圆形区域,圆心坐标(50,50),半径为30,填充颜色为蓝色

  • 未使用CImg的接口函数
void DrawCircle_blue1(CImg <unsigned char> TempImg) {
	CImg<unsigned char> SrcImg = TempImg;
	cimg_forXY(SrcImg, x, y) {
		if (pow(pow(x-50,2)+pow(y-50,2),0.5) < 30) {
			SrcImg(x,y,0) = 0;
			SrcImg(x,y,1) = 0;
			SrcImg(x,y,2) = 255;
		}
	}
	SrcImg.display("work3.1");
}

这里写图片描述

  • 使用接口函数draw_circle()
void DrawCircle_blue2(CImg <unsigned char> TempImg) {
	unsigned char blue[] = {0,0,255};
	TempImg.draw_circle(50, 50, 30, blue);
	TempImg.display("work3.2");
}

这里写图片描述

PS: 这个感觉自己实现的算法和接口函数实现的效果差不多

5. 在图上绘制一个圆形区域,圆心坐标(50,50),半径为3,填充颜色为黄色

  • 未使用CImg的接口函数
void DrawCircle_yellow1(CImg <unsigned char> TempImg) {
	CImg<unsigned char> SrcImg = TempImg;
	cimg_forXY(SrcImg, x, y) {
		if (pow(pow(x-50,2)+pow(y-50,2),0.5) < 3) {
			SrcImg(x,y,0) = 200;
			SrcImg(x,y,1) = 155;
			SrcImg(x,y,2) = 0;
		}
	}
	SrcImg.display("work4.1");
}
![这里写图片描述](https://img-blog.csdn.net/20180911172544111?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlcnJ5MDUyOA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

这里写图片描述

  • 使用接口函数draw_circle()
void DrawCircle_yellow2(CImg <unsigned char> TempImg) {
	unsigned char yellow[] = {200, 155, 0};
	TempImg.draw_circle(50, 50, 3, yellow);
	TempImg.display("work4.2");
}

这里写图片描述

PS: 这个虽然接口函数的效果也并不是特别好,但是明显比我的要好很多,但是因为遍历图片的像素点是对图片进行采样所以点坐标为整数值,圆的半径越小意味着我们取的像素点范围越少,点越少,所以图片的效果会较差,甚至接近正方形,可能接口的函数有更好的实现方法,尝试去翻了翻源码没太看懂

6. 在图上绘制一条长为100的直线段,起点坐标为(0, 0),方向角为35度,直线的颜色为蓝色

  • 未使用CImg的接口函数
void DrawLine1(CImg <unsigned char> TempImg) {
	CImg<unsigned char> SrcImg = TempImg;
	double x0 = 100*cos(35*pi/180);
	double y0 = 100*sin(35*pi/180);
	cimg_forXY(SrcImg, x, y) {
		if (x == 0) {
			if (y == 0) {
				SrcImg(x,y,0) = 0;
				SrcImg(x,y,1) = 0;
				SrcImg(x,y,2) = 255;
			}
		}
		else {
			if (cmp((double)y, (double)x*tan(35*pi/180)) && (double)x <= x0 && (double)y <= y0) {
				SrcImg(x,y,0) = 0;
				SrcImg(x,y,1) = 0;
				SrcImg(x,y,2) = 255;
			}
		}
	}
	SrcImg.display("work5.1");
}
//用于上面函数的一个辅助函数,来判断相等条件
bool cmp(double x , double y) { //compare x and y,如果差值小于一定范围则近似相等
	if (abs(x - y) <= 0.5)
		return 1;
	return 0;
}

这里写图片描述

  • 使用接口函数draw_line()
void DrawLine2(CImg <unsigned char> TempImg) {
	unsigned char blue[] = {0,0,255};
	TempImg.draw_line(0,0,100*cos(35*pi/180),100*sin(35*pi/180),blue);
	TempImg.display("work5.2");
}

这里写图片描述

PS: 这个比较效果感觉肉眼很难看出差距,但是因为遍历图片的像素点是对图片进行采样所以点坐标为整数值,所以不可能存在彻底等于所得的浮点数tan角要求的坐标,只能通过设置误差尽可能小,也就是直线的粗细,通过设置cmp函数调节几个值(0.1, 0.3, 0.5, 1.0)发现0.5的效果是最好的。

7. 把上面的操作结果保存为 2.bmp

SrcImg.save("2.bmp");

3. 将上述实现的函数封装为c++的一个类

ex.hpp:

#ifndef _EX_HPP_
#define _EX_HPP_
#include "../CImg.h"
#include <cmath>
#include <string>
using namespace std;
using namespace cimg_library;
const double pi(3.14159265);
class Test
{
	public:
		Test();
		~Test();
		void Todisplay();
		void change(); //把1.bmp文件的白色区域变成红色,黑色区域变成绿色
		void DrawCircle_blue1(); //不使用CImg函数在图上绘制一个圆形区域,圆心坐标(50,50),半径为30,填充颜色为蓝色
		void DrawCircle_yellow1();//不使用CImg函数在图上绘制一个圆形区域,圆心坐标(50,50),半径为3,填充颜色为黄色
		void DrawLine1();//不使用CImg函数 在图上绘制一条长为100的直线段,起点坐标为(0, 0),方向角为35度,直线的颜色为蓝色。 
		//下面三个函数分别对应使用CImg函数的上述三个操作
		void DrawCircle_blue2();
		void DrawCircle_yellow2();
		void DrawLine2();
		CImg<unsigned char> getSrcImg();
	private:
		//string name; //图片的名称
		CImg<unsigned char> SrcImg; //定义一副图片
};
#endif

ex.cpp

#include "ex.hpp"
using namespace std;
bool cmp(double x , double y);

Test::Test() {
	//name = "work1";
	SrcImg.load_bmp("1.bmp");
}

Test::~Test() {}

void Test::Todisplay() {
	//string t = name;
	SrcImg.display("homework");
}

CImg<unsigned char> Test::getSrcImg() {
	return SrcImg;
}

void Test::change() {
	//name = "work2";
	//CImg<unsigned char> Img = SrcImg;
	cimg_forXY(SrcImg, x, y) {
		if (SrcImg(x,y,0) == 255 && SrcImg(x,y,1) == 255 && SrcImg(x,y,2) == 255) {
			SrcImg(x,y,0) = 255;
			SrcImg(x,y,1) = 0;
			SrcImg(x,y,2) = 0;
 		}
	}
	cimg_forXY(SrcImg, x, y) {
		if (SrcImg(x,y,0) == 0 && SrcImg(x,y,1) == 0 && SrcImg(x,y,2) == 0) {
			SrcImg(x,y,0) = 0;
			SrcImg(x,y,1) = 255;
			SrcImg(x,y,2) = 0;
 		}
	}
}

void Test::DrawCircle_blue1() {
	cimg_forXY(SrcImg, x, y) {
		if (pow(pow(x-50,2)+pow(y-50,2),0.5) < 30) {
			SrcImg(x,y,0) = 0;
			SrcImg(x,y,1) = 0;
			SrcImg(x,y,2) = 255;
		}
	}
}

void Test::DrawCircle_yellow1() {
	cimg_forXY(SrcImg, x, y) {
		if (pow(pow(x-50,2)+pow(y-50,2),0.5) < 3) {
			SrcImg(x,y,0) = 200;
			SrcImg(x,y,1) = 155;
			SrcImg(x,y,2) = 0;
		}
	}
}

void Test::DrawLine1() {
	double x0 = 100*cos(35*pi/180);
	double y0 = 100*sin(35*pi/180);
	cimg_forXY(SrcImg, x, y) {
		if (x == 0) {
			if (y == 0) {
				SrcImg(x,y,0) = 0;
				SrcImg(x,y,1) = 0;
				SrcImg(x,y,2) = 255;
			}
		}
		else {
			if (cmp((double)y, (double)x*tan(35*pi/180)) && (double)x <= x0 && (double)y <= y0) {
				SrcImg(x,y,0) = 0;
				SrcImg(x,y,1) = 0;
				SrcImg(x,y,2) = 255;
			}
		}
	}
}

void Test::DrawCircle_blue2() {
	unsigned char blue[] = {0,0,255};
	SrcImg.draw_circle(50, 50, 30, blue);
}

void Test::DrawCircle_yellow2() {
	unsigned char yellow[] = {200, 155, 0};
	SrcImg.draw_circle(50, 50, 3, yellow);
}
		
void Test::DrawLine2() {
	unsigned char blue[] = {0,0,255};
	SrcImg.draw_line(0,0,100*cos(35*pi/180),100*sin(35*pi/180),blue);
}

bool cmp(double x , double y) { //compare x and y,如果差值小于一定范围则近似相等
	if (abs(x - y) <= 0.5)
		return 1;
	return 0;
}

main.cpp

#include "ex.hpp"
using namespace std;
int main(int argc, char const *argv[])
{
	Test pic;
	Test pic1;
	pic.change();
	pic.DrawCircle_blue1();
	pic.DrawCircle_yellow1();
	pic.DrawLine1();
	pic.Todisplay();
	CImg<unsigned char> temp = pic.getSrcImg();
	temp.save("2.bmp");
	pic1.change();
	pic1.DrawCircle_blue2();
	pic1.DrawCircle_yellow2();
	pic1.DrawLine2();
	pic1.Todisplay();
	CImg<unsigned char> temp1 = pic1.getSrcImg();
	temp1.save("2.1.bmp");
	return 0;
}

运行并存储后实现的整体效果图如下所示:
(1) 未使用接口函数:
这里写图片描述
(2) 使用接口函数:
这里写图片描述

完整代码参见:
https://github.com/WangPerryWPY/Computer-Version/tree/master/EX1

  • 1
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值