学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为1907字,预计阅读5分钟
前言
上一篇《OpenCV图片动态特效显示(一)--展开显示》介绍了图像的展开显示特效,这一篇我们还是在原来的Demo基础上加入图片的渐显和马赛克显示。
实现效果
上面的动图中可以看到,左边的是马赛克显示,右边的就是渐渐显示的效果,我们分别来说一下实现方式。
马赛克显示

微卡智享
实现思路
# | 实现步骤 |
---|---|
1 | 设置马赛克正方形的大小,将图像分割成多个马赛克 |
2 | 把每个马赛克的左上角的坐标点存放到容器中 |
3 | 把容器中的坐标点顺序随机打乱 |
4 | 遍历已经打乱的容器逐步显示出图像 |
核心代码
//马赛克显示
//参数:src 源图像,
// width 源图像宽度,
// height 源图像高度,
// sidelength 马赛克的边长
//思路:1.根据设置的边长定义图像中马赛克的正方形小块,
// 把每个小块的左上角坐标记录下来存放到vector的容器中
// 2.然后把vector的容器顺序打乱
// 3.遍历容器里的坐标显示出图像
void mosaicshow(Mat src, int width, int height, int sidelength)
{
Mat dst = Mat(src.size(), CV_8UC3);
//定义坐标点容器
vector<Point2f> vtpoints;
//遍历图像将正方形小块左上角点存到容器中
for (int col = 0; col < width; col = col + sidelength) {
for (int row = 0; row < height; row = row + sidelength) {
//如果宽度超出图像最右边的正方形点后设置最右边点
if (col > width - sidelength) {
col = width - sidelength;
}
//如果高度超出图像最下面的正方形高度同上原理
if (row > height - sidelength) {
row = height - sidelength;
}
//将坐标点存入到容器中
vtpoints.push_back(Point2f(col, row));
}
}
//打乱容器内的坐标点
random_shuffle(vtpoints.begin(), vtpoints.end());
//遍历容器显示每个马赛克
for (Point2f pt : vtpoints)
{
src(Rect(pt.x, pt.y, sidelength, sidelength))
.copyTo(dst(Rect(pt.x, pt.y, sidelength, sidelength)));
imshow("mosaicshow", dst);
waitKey(1);
}
waitKey(0);
}
渐显

微卡智享
实现思路
# | 实现步骤 |
---|---|
1 | 先从源图复制一个目标图像出来 |
2 | 记录下源图像中每个像素点的值 |
3 | 循环从黑到白的遍历(n=1....256) |
4 | 遍历的过程中把每个像素点的值*n/256再显示出来 |
核心代码
//图像渐显
//参数:Mat 源图像,
// width图像宽度,
// height图像高度
//思路:1.记录下图像每个像素点的像素值,显示的时候先将屏幕置黑
// 2.循环显示图像N次,每次显示像素值为N/256倍
void graduallyshow(Mat src, int width, int height)
{
Mat dst;
dst = src.clone();
//考虑到三通道RGB的问题,所以宽度这里要乘3
int tmpwidth = width * 3;
for (int n = 1; n < 256; ++n) {
for (int row = 0; row < height; ++row) {
uchar* data1 = src.ptr<uchar>(row);
uchar* data2 = dst.ptr<uchar>(row);
for (int col = 0; col < tmpwidth; ++col) {
data2[col] = data1[col] * n / 256;
}
}
imshow("graduallyshow", dst);
waitKey(1);
}
cout << "graduallyshow" << endl;
waitKey(0);
}
线程调用
调用代码
//图像渐显
future<void> ftgradually = async(launch::async, graduallyshow, src, src.cols, src.rows);
//马赛克显示
future<void> ftmosaic = async(launch::async, mosaicshow, src, src.cols, src.rows, 20);
实现开头同时显示的方式还是用到了线程,也是上一篇中我们已经用到过的。
完
扫描二维码
获取更多精彩
微卡智享
「 往期文章 」