滚动条操作
//Mat对象
Mat dst, m, src;
int lightness = 50; //初始亮度
void on_track(int, void *)
{
//初始化m对象
m = Scalar(lightness, lightness, lightness);
cv::add(src, m, dst); //增加光的亮度
//将dst放在主布局nameWindow之下
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image)
{
//nameWindow属于主布局
namedWindow("亮度调整", WINDOW_AUTOSIZE);
dst = Mat::zeros(image.size(), image.type());
m = Mat::zeros(image.size(), image.type());
src = image.clone(); //深拷贝
int max_value = 100;
//当滚动按钮被拖动的时候,on_track函数会去调整光的亮度
createTrackbar("亮度调整: ", "亮度调整", &lightness,
max_value, on_track);
on_track(50, 0); //固定写法
}
//main.cpp
int main()
{
cv::Mat src = imread("C:\\Users\\26961\\Desktop\\images\\dog.jpg");
if (src.empty()) {
cout << "图片未打开" << endl;
return -1;
}
QuickDemo obj;
obj.tracking_bar_demo(src);
//阻塞等待
waitKey(0);
//销毁窗口对象
destroyAllWindows();
return 0;
}
滚动条程序通过参数传递
void on_track(int lightness,void* Matobj)
{
//取出Mat对象,做加法运算
Mat src = (*(Mat*)Matobj).clone();
Mat dst = Mat::zeros(src.size(), src.type());
Mat m = static_cast<Mat>(Scalar(lightness, lightness, lightness));
add(src, m, dst);
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image)
{
//指定主窗口
namedWindow("亮度调整", WINDOW_AUTOSIZE);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
Mat src = image.clone();
int max_value = 100;
int lightness = 50;
createTrackbar("亮度调整", "亮度调整", &lightness, max_value, on_track,
(Mat *)&image);
on_track(50 ,(void *)&image);
}
亮度跟对比度的调整
- 亮度的调整会将整张图片的亮度进行调高
- 对比亮度的调整虽然会将整张图片的亮度调高,但是由于一开始的差距所以导致的亮度不一致。
对比度的调整
void on_contrast(int lightness, void* Matobj)
{
//取出Mat对象,做加法运算
Mat src = (*(Mat*)Matobj).clone();
Mat dst = Mat::zeros(src.size(), src.type());
Mat m = Mat::zeros(src.size(), src.type());
double contrast = lightness / 100.0;
addWeighted(src, contrast, m, 0.0, 0, dst);
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image)
{
//指定主窗口
namedWindow("亮度调整", WINDOW_AUTOSIZE);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
Mat src = image.clone();
int contrast_value = 50;
createTrackbar("对比度调整", "亮度调整", &contrast_value, 200, on_contrast,
(void*)&image);
on_contrast(50, &image);
}
键盘响应操作
键盘上一些常用的键盘键值表:
void QuickDemo::Key_demo(Mat& image)
{
while (true)
{
int c = waitKey(100);
if (c == 27) {
break;
}
if (c == 49) {
std::cout << "你输入的是1" << std::endl;
}
if (c == 50) {
std::cout << "你输入的是2" << std::endl;
}
if (c == 51) {
std::cout << "你输入的是3" << std::endl;
}
}
}
waitKey会等待用户到键盘按下,之后会收到一个值,在判断之后显示对应的内容,这里主要是演示通过opencv接口和键盘之间的交互,为了方便后面通过键盘给图片改变颜色做铺垫。
输入窗口按下按钮后,对应的输出窗口可以获取一个值,接下来可以通过按件来控制需要生成什么样的图片了。
如何通过键盘的按键生成色彩不同的图片呢?
void QuickDemo::Key_demo(Mat& image)
{
Mat hsv, gray; //彩色图和灰色图
Mat dst = Mat::zeros(image.size(), image.type());
while (true)
{
int c = waitKey(100);
if (c == 27) {
break;
}
if (c == 49) {//1号键灰色
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰色", gray);
}
if (c == 50) {//2号键彩色
cvtColor(image, hsv, COLOR_RGB2HSV);
imshow("hsv", hsv);
}
if (c == 51) { //3号键自定义调色
std::cout << "请输入色彩值" << std::endl;
int x, y, z;
std::cin >> x >> y >> z; //对应B、G、R的值
dst = static_cast<Mat>(Scalar(x, y, z));
add(image, dst, dst);
imshow("自定义调色", dst);
}
}
}
颜色表
这里列举opencv自带的颜色表,可以通过搭配颜色表中的配色方案,完成image对象的调色处理,最终可以选择保存该图片
void QuickDemo::set_color_style(Mat &image)
{
//定义颜色表
static int colormap[] = {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA,
COLORMAP_MAGMA,
COLORMAP_INFERNO,
COLORMAP_PLASMA,
COLORMAP_VIRIDIS,
COLORMAP_CIVIDIS,
COLORMAP_TWILIGHT,
COLORMAP_TWILIGHT_SHIFTED,
};
int len = sizeof(colormap) / sizeof(colormap[0]);
//通过遍历颜色表的方式,获取applyColorMap处理后每一张具有特色的图片
Mat dst = Mat::zeros(image.size(), image.type());
int index = 0;
while (true) {
int x = waitKey(100);
if (x == 27) //27是ESC键的键值。
break;
applyColorMap(image, dst, colormap[(index++) % len]);
imshow("自由图片播放", dst);
if (x == 83) { //保存该图片, 83是大写S的键值
//拼接路径
std::string path = "C:\\Users\\26961\\Desktop\\images\\";
std::string str(std::to_string(index) + ".jpg");
path.append(str);
std::cout << "保存图片" << path << std::endl;
//将图片写入路径中。
imwrite(path, dst);
}
}
}
图像像素的逻辑操作
Rect(int x, int y, int width, int height);
该函数的四个参数(x , y) 表示左上角的坐标,width表示需要绘制的矩形的宽,height表示需要绘制矩形的高度。
rectangle(matobj, rect(x, y, width, height), Scalar(G, B, R), -1, LINE_8, 0);
// Mat对象 绘制矩形的大小 色彩 第四个参数 < 0表示填充, 大于0表示绘制线宽
// 由于第四个参数选用的是-1, 所以当第五个参数选用的是LINE_8的时候会将周围的8个像素点拿来填充
填充矩形
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//填充 80 * 80的黄色矩形 和蓝色矩形
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(0, 0, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
}
绘制矩形只需要将rectangle的第三个参数改到大于0就行。
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//绘制 80 * 80的黄色矩形 和蓝色矩形
//
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), 2, LINE_8, 0);
rectangle(m2, Rect(0, 0, 80, 80), Scalar(0, 255, 255), 2, LINE_AA, 0);
imshow("m1", m1);
imshow("m2", m2);
}
可以看出明显的区别绘制的矩形中间是属于空心的
位操作
bitwise_and 按位与操作
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//填充 80 * 80的黄色矩形 和蓝色矩形
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
//Mat对象位运算
Mat dst = Mat::zeros(Size(200, 200), CV_8UC3);
bitwise_and(m1, m2, dst);
imshow("按位与操作", dst);
}
m1 对象和m2对象按位与之后会得到dst对象, 这就是按位与之后的结果。
像素点的按位或操作 bitwise_or
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//填充 80 * 80的黄色矩形 和蓝色矩形
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
//Mat对象位运算
Mat dst = Mat::zeros(Size(200, 200), CV_8UC3);
bitwise_or(m1, m2, dst);
imshow("按位与操作", dst);
}
bitwise_not 按位取反操作
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//填充 80 * 80的黄色矩形 和蓝色矩形
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
//Mat对象位运算
Mat dst = Mat::zeros(Size(200, 200), CV_8UC3);
bitwise_not(m1 , dst);
imshow("按位与操作", dst);
}
m1对象的取反结果就是dst,可以看出m1的背景色是黑色而取反之后的结果确是白色,m1的矩形是蓝色,取反后的矩形是红色。
bitwise_xor按位异或操作
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(200, 200), CV_8UC3);
Mat m2 = Mat::zeros(Size(200, 200), CV_8UC3);
//填充 80 * 80的黄色矩形 和蓝色矩形
rectangle(m1, Rect(100, 100, 80 , 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
//Mat对象位运算
Mat dst = Mat::zeros(Size(200, 200), CV_8UC3);
bitwise_xor(m1, m2, dst);
imshow("按位与操作", dst);
}
蓝色和黄色相同的部分会被直接异或成紫色,而不同的部分则会继续保留这就是异或操作