精华内容
下载资源
问答
  • Python实现图片对比

    千次阅读 2019-09-19 11:52:03
    具体实现逻辑:使用第三方的控件,将两张图片进行对比,两张图片的尺寸必须一致。然后才能对比。 # USAGE # python image_diff.py --first images/original_01.png --second images/modified_01.png # import the ...

    以下内容转载自大牛该大牛,链接点击跳转

    具体实现逻辑:使用第三方的控件,将两张图片进行对比,两张图片的尺寸必须一致。然后才能对比。

    # USAGE
    # python image_diff.py --first images/original_01.png --second images/modified_01.png
    
    # import the necessary packages
    from skimage.measure import compare_ssim
    import argparse
    import imutils
    import cv2
    
    # construct the argument parse and parse the arguments
    ap = argparse.ArgumentParser()
    ap.add_argument("-f", "--first", required=True,
        help="first input image")
    ap.add_argument("-s", "--second", required=True,
        help="second")
    args = vars(ap.parse_args())
    
    # load the two input images
    imageA = cv2.imread(args["first"])
    imageB = cv2.imread(args["second"])
    
    # convert the images to grayscale
    grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
    grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
    
    # compute the Structural Similarity Index (SSIM) between the two
    # images, ensuring that the difference image is returned
    (score, diff) = compare_ssim(grayA, grayB, full=True)
    diff = (diff * 255).astype("uint8")
    print("SSIM: {}".format(score))
    
    # threshold the difference image, followed by finding contours to
    # obtain the regions of the two input images that differ
    thresh = cv2.threshold(diff, 0, 255,
        cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    
    # loop over the contours
    for c in cnts:
        # compute the bounding box of the contour and then draw the
        # bounding box on both input images to represent where the two
        # images differ
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
    # show the output images
    cv2.imshow("Original", imageA)
    cv2.imshow("Modified", imageB)
    cv2.imshow("Diff", diff)
    cv2.imshow("Thresh", thresh)
    cv2.waitKey(0)
    
    展开全文
  • 基于j2me的图片特效(缩放,裁剪,调整大小,镜像,对比度亮度调整,黑白,线条,粉笔) 源码 封装好了类
  • 可在图片点做对比,上下的图片点的位置是一样的,但因颜色只写了20个,最多可20个点, 撤销点的操作快捷方式 左图: l键 右图: r键 图片需要先保存之后才可以下载 demo下面的长形图片,是因某需求要放大图片...
  • 支持手动调整ASCII码密度水平,图片亮度、对比度和抖动程度;支持自定义字母及数字,支持选取图片一部分来生成字符;支持批量生成字符,支持黑白或彩色输出;支持纯文本、图片、html等文件输出。
  • 帧动画的多种实现方式与性能对比

    万次阅读 2018-07-11 10:42:47
    每张图片首次加载会造成图片切换时的闪烁 不利于文件的管理 (2)连续切换雪碧图位置(推荐) 我们将所有的帧动画图片合并成一张雪碧图,通过改变 background-position 的值来实现动画帧切换。分两步进行...


    Web动画形式

    首先我们来了解一下Web有哪些动画形式

    1. CSS3动画
        Transform(变形)
        Transition(过渡)
        Animation(动画)
    2. JS动画(操作DOM、修改CSS属性值)
    3. Canvas动画
    4. SVG动画
    5. 以Three.js为首的3D动画
    

    以上各种动画形式都可以制作出一种类型的动画,那就是帧动画,也叫序列帧动画,定格动画,逐帧动画等,这里我们统一用帧动画来表述。

    这里写图片描述

    应用场景

    帧动画一般用来实现稍微复杂一点的动画效果,同时希望动画更细腻,设计师更自由的发挥。他可以定义到每一个时间刻度上的展现内容,我们一般用帧动画来做页面的Loading,小人物,小物体元素的简单动画。我们想象中的帧动画应该有以下几个特点:

    1. 可以自由控制播放、暂停和停止
    2. 可以控制播放次数,播放速度
    3. 可以添加交互,在播放完成后添加事件
    4. 浏览器兼容性好

    素材准备

    帧动画的素材一般是先由设计师在PS中的时间轴上设计好了,然后导出图片给前端人员,PS制作时间轴动画一般是用来制作稍微简单的动画,操作简单,方便。

    或者是由设计师在AE的时间轴进行设计,因为AE内置了更丰富的动作效果,比如转换,翻转之类的,AE可以帮助我们实现更复杂的效果,然后再导出图片给前端人员。

    这里帧动画素材的要求,每一帧的图片最好是偶数宽高,偶数张,最好周围能有一些留白。

    实现方案

    将目前想到的解决方案梳理如下图,同时我们将对每种方案进行详细介绍。
    这里写图片描述

    一、GIF图

    我们可以将上面制作的帧动画导出成GIF图,GIF图会连续播放,无法暂停,它往往用来实现小细节动画,成本较低、使用方便。但其缺点也是很明显的:

    1. 画质上,gif 支持颜色少(最大256色)、Alpha 透明度支持差,图像锯齿毛边比较严重;
    2. 交互上,不能直接控制播放、暂停、播放次数,灵活性差;
    3. 性能上,gif 会引起页面周期性的绘画,性能较差。

    二、CSS3帧动画

    CSS3帧动画是我们今天需要重点介绍的方案,最核心的是利用CSS3中Animation动画,确切的说是使用animation-timing-function 的阶梯函数 steps(number_of_steps, direction) 来实现逐帧动画的连续播放。

    帧动画的实现原理是不断切换视觉内图片内容,利用视觉滞留生理现象来实现连续播放的动画效果,下面我们来介绍制作CSS3帧动画的几种方案。

    (1)连续切换动画图片地址src(不推荐)

    我们将图片放到元素的背景中(background-image),通过更改 background-image 的值实现帧的切换。但是这种方式会有以下几个缺点,所以该方案不推荐。

    • 多张图片会带来多个 HTTP 请求
    • 每张图片首次加载会造成图片切换时的闪烁
    • 不利于文件的管理

    (2)连续切换雪碧图位置(推荐)

    我们将所有的帧动画图片合并成一张雪碧图,通过改变 background-position 的值来实现动画帧切换。分两步进行:

    步骤一: 将动画帧合并为雪碧图,雪碧图的要求可以看上面素材准备,比如下面这张帧动画雪碧图,共20帧。
    这里写图片描述

    步骤二: 使用steps阶梯函数切换雪碧图位置

    先看写法一:

    <div class="sprite"></div>
    
    .sprite {
        width: 300px;
        height: 300px;
        background-repeat: no-repeat;
        background-image: url(frame.png);
        animation: frame 333ms steps(1,end) both infinite;
    }
    @keyframes frame {
        0% {background-position: 0 0;}
        5% {background-position: -300px 0;}
        10% {background-position: -600px 0;}
        15% {background-position: -900px 0;}
        20% {background-position: -1200px 0;}
        25% {background-position: -1500px 0;}
        30% {background-position: -1800px 0;}
        35% {background-position: -2100px 0;}
        40% {background-position: -2400px 0;}
        45% {background-position: -2700px 0;}
        50% {background-position: -3000px 0;}
        55% {background-position: -3300px 0;}
        60% {background-position: -3600px 0;}
        65% {background-position: -3900px 0;}
        70% {background-position: -4200px 0;}
        75% {background-position: -4500px 0;}
        80% {background-position: -4800px 0;}
        85% {background-position: -5100px 0;}
        90% {background-position: -5400px 0;}
        95% {background-position: -5700px 0;}
        100% {background-position: -6000px 0;}
    }
    

    针对以上动画有疑问?

    问题一:既然都详细定义关键帧了,是不是可以不用steps函数了,直接定义linear变化不就好了吗?

    animation: frame 10s linear both infinite;

    如果我们定义成这样,动画是不会阶梯状,一步一步执行的,而是会连续的变化背景图位置,是移动的效果,而不是切换的效果,如下图:

    这里写图片描述

    问题二:不是应该设置为20步吗,怎么变成了1?

    这里我们先来了解下animation-timing-function属性。

    CSS animation-timing-function属性定义CSS动画在每一动画周期中执行的节奏。对于关键帧动画来说,timing function作用于一个关键帧周期而非整个动画周期,即从关键帧开始开始,到关键帧结束结束。

    timing-function 作用于每两个关键帧之间,而不是整个动画。

    接着我们来了解下steps() 函数:

    • steps 函数指定了一个阶跃函数,它接受两个参数。
    • 第一个参数接受一个整数值,表示两个关键帧之间分几步完成。
    • 第二个参数有两个值< start > or < end >。默认值为< end > 。
    • step-start 等同于 step(1, start)。step-end 等同于 step(1, end)。

    综上我们可以知道,因为我们详细定义了一个关键帧周期,从开始到结束,每两个关键帧之间分 1 步展示完,也就是说0% ~ 5%之间变化一次,5% ~ 10%变化一次,所以我们这样写才能达到想要的效果。

    再看写法二:

    <div class="sprite"></div>
    
    .sprite {
        width: 300px;
        height: 300px;
        background-repeat: no-repeat;
        background-image: url(frame.png);
        animation: frame 333ms steps(20) both infinite;
    }
    @keyframes frame {
        0% {background-position: 0 0;}//可省略
        100% {background-position: -6000px 0;}
    }
    

    这里我们定义了关键帧的开始和结束,也就是定义了一个关键帧周期,但因为我们没有详细的定义每一帧的展示,所以我们要将0%~100%这个区间分成20步来阶段性展示。

    也可以换成关键字的写法,还可以只定义最后一帧,因为默认第一帧就是初始位置。

    @keyframes frame {
        from {background-position: 0 0;}//可省略
        to {background-position: -6000px 0;}
    }
    

    (3)连续移动雪碧图位置(移动端推荐)

    跟第二种基本一致,只是切换雪碧图的位置过程换成了transform:translate3d()来实现,不过要加多一层overflow: hidden;的容器包裹,这里我们以只定义初始和结束帧为例,使用transform可以开启GPU加速,提高机器渲染效果,还能有效解决移动端帧动画抖动的问题。

    <div class="sprite-wp">
        <div class="sprite"></div>
    </div>
    
    .sprite-wp {
        width: 300px;
        height: 300px;
        overflow: hidden;
    }
    .sprite {
        width: 6000px;
        height: 300px;
        will-change: transform;
        background: url(frame.png) no-repeat center;
        animation: frame 333ms steps(20) both infinite;
    }
    @keyframes frame {
    	0% {transform: translate3d(0,0,0);}
        100% {transform: translate3d(-6000px,0,0);}
    }
    

    三、JS帧动画

    (1)通过JS来控制img的src属性切换(不推荐)

    和上面CSS3帧动画里面切换元素background-image属性一样,会存在多个请求等问题,所以该方案我们不推荐,但是这是一种解决思路。

    (2)通过JS来控制Canvas图像绘制

    通过Canvas制作帧动画的原理是用drawImage方法将图片绘制到Canvas上,不断擦除和重绘就能得到我们想要的效果。

    <canvas id="canvas" width="300" height="300"></canvas>
    
    (function () {
        var timer = null,
            canvas = document.getElementById("canvas"),
            context = canvas.getContext('2d'),
            img = new Image(),
            width = 300,
            height = 300,
            k = 20,
            i = 0;
        img.src = "frame.png";
    
        function drawImg() {
            context.clearRect(0, 0, width, height);
            i++;
            if (i == k) {
                i = 0;
            }
            context.drawImage(img, i * width, 0, width, height, 0, 0, width, height);
            window.requestAnimationFrame(drawImg);
        }
        img.onload = function () {
            window.requestAnimationFrame(drawImg);
        }
    })();
    

    上面是通过改变裁剪图像的X坐标位置来实现动画效果的,也可以通过改变画布上放置图像的坐标位置实现,如下:
    context.drawImage(img, 0, 0, width*k, height,-i*width,0,width*k,height);

    (3)通过JS来控制CSS属性值变化

    这种方式和前面CSS3帧动画一样,有三种方式,一种是通过JS切换元素背景图片地址background-image,一种是通过JS切换元素背景图片定位background-position,最后一种是通过JS移动元素transform:translate3d(),第一种不做介绍,因为同样会存在多个请求等问题,不推荐使用,这里实现后面两种。

    • 切换元素背景图片位置 background-position
    .sprite {
        width: 300px;
        height: 300px;
        background: url(frame.png) no-repeat 0 0;
    }
    
    <div class="sprite" id="sprite"></div>
    
    (function(){
        var sprite = document.getElementById("sprite"),
    	    picWidth = 300,
    	    k = 20,
    	    i = 0,
    	    timer = null;
        // 重置背景图片位置
        sprite.style = "background-position: 0 0";
        // 改变背景图位置
        function changePosition(){
            sprite.style = "background-position: "+(-picWidth*i)+"px 0";
            i++;
            if(i == k){
                i = 0;
            }
            window.requestAnimationFrame(changePosition);
        }
        window.requestAnimationFrame(changePosition);
    })();
    
    • 移动元素背景图片位置 transform:translate3d()
    .sprite-wp {
       width: 300px;
        height: 300px;
        overflow: hidden;
    }
    .sprite {
        width: 6000px;
        height: 300px;
        will-change: transform;
        background: url(frame.png) no-repeat center;
    }
    
    <div class="sprite-wp">
        <div class="sprite" id="sprite"></div>
    </div>
    
    (function () {
        var sprite = document.getElementById("sprite"),
            picWidth = 300,
            k = 20,
            i = 0,
            timer = null;
        // 重置背景图片位置
        sprite.style = "transform: translate3d(0,0,0)";
        // 改变背景图移动
        function changePosition() {
            sprite.style = "transform: translate3d(" + (-picWidth * i) + "px,0,0)";
            i++;
            if (i == k) {
                i = 0;
            }
            window.requestAnimationFrame(changePosition);
        }
        window.requestAnimationFrame(changePosition);
    })();
    

    方案总结

    总结以上几种方案,我们可以看到GIF图有一定的优点同时缺点和局限性也比较明显,所以这种方案看情况选择使用。

    其他实现方案的性能如何呢,我们来比较一下,如果测试结果出现偏差,可能与测试环境变化有关。

    测试环境:

    系统:Windows 10 专业版
    处理器:Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz 3.41GHz
    RAM: 8.00GB
    浏览器:Chrome 72.0
    

    CSS  方案性能数据

    CSS transform:translate3d() 方案性能数据

    如上图,我们通过Chrome浏览器的各种工具,查看了每种方案的 FPS、CPU占用率、GPU占用、Scripting、Rendering、Painting、内存的使用情况,得到以下数据:

    性能-方案cssbackground-positioncsstransform:translate3d()JS CanvasJSbackground-positionJStransform:translate3d()
    FPS6051606060
    CPU5%-6.2%0.3%-1%7%-8%6%-8%6%-8%
    GPU3.8MB4-10MB03.8MB4-11MB
    Scripting002.51%2.61%3.18%
    Rendering1.17%0.141%0.84%1.65%2.71%
    Painting1.58%0.01%1.63%1.75%1.05%
    内存20112K21120K21588K20756K21576K

    通过分析以上数据我们可以得出以下几点:

    1. 除了css transform:translate3d() 方案,其他方案的FPS都能达到60FPS的流畅程度,但该方案的FPS也不是很低。
    2. CPU占用率最低的方案是 css transform:translate3d() 方案。
    3. GPU占用最低的方案是 JS Canvas 绘制方案。
    4. CSS 方案没有脚本开销
    5. Rendering 最少的是 css transform:translate3d() 方案。
    6. Painting 最少的是 css transform:translate3d() 方案。
    7. 各方案内存占用区别不大。

    结论:我们看到,在7个指标中,css transform:translate3d() 方案将其中的4个指标做到了最低,从这点看,我们完全有理由选择这种方案来实现CSS帧动画。

    至于其他方案的绝对比较暂时没法给出结论,看具体情况来选择,也看开发者对哪个性能指标的追求。

    延伸来看我们的Web动画,每种形式的动画都有其各自的有点,比如大量的粒子效果用Canvas绘制方案肯定要比DOM+CSS实现要好的,大量的CSS属性值变换,使用 transform 实现性能是要更好的。

    注意事项

    素材:动画图片宽高最好是偶数,总帧数最好是偶数,图片拼接处最好有一定的留白。

    适配:移动端适配最好不用rem,因为rem的计算会造成小数四舍五入,造成一定的抖动效果,建议直接用px作为单位,同时辅助以scale(zoom)媒体查询进行适配。如果使用rem适配,试试使用transform的方案,抖动问题可以得到优化解决。

    对于帧与帧之间的盈亏互补现象导致动画抖动,想要了解更多,可以阅读《CSS技巧:逐帧动画抖动解决方案》

    tips:使用 will-change 可以在元素属性真正发生变化之前提前做好对应准备。

    总结

    本文我们主要梳理了目前实现帧动画的几种方案,同时对各种方案进行效果实现,优劣讨论,性能对比,同时简单介绍了帧动画实现过程的注意事项,最后我们得出结论,css transform:translate3d() 方案在实现和性能上都明显优于其他方案。

    参考来源:

    1. 《CSS3动画之逐帧动画》
    2. 《指尖上行》
    展开全文
  • OpenCV图片漫画效果

    千次阅读 多人点赞 2020-08-10 00:02:29
    对比现实中的画画,一般是先出边缘轮廓使整体规划好,再填充颜色使其完整,因此在这里我们也采用这种方式。不过对图片直接操作与从零开始着笔不一样,要将原始图片进行两次不同的处理,再将处理后的

    我们随手拍摄的照片,很难达到摄影师的水准,因此不管是手机上还是电脑内,都有一些软件可以添加特效让照片更好看,手机拍摄时也有即时的美化效果。不过我比较好奇漫画特效,但是一直在网上看到别人的成品而找不到针对性的软件,因此只有自己实现一下,虽然跟专业的还有差距,但效果还不错。

    本次使用 OpenCV,采用 Python 实现。


    对比现实中的画画,一般是先画出边缘轮廓使整体规划好,再填充颜色使其完整,因此在这里我们也采用这种方式。不过对图片直接操作与从零开始着笔不一样,要将原始图片进行两次不同的处理,再将处理后的两个图片叠加。

    边缘轮廓

    漫画中不管是人物还是风景,刻画的细节有限,因此需要把重要以及有特色的部分体现出来,数量要适当。

    轮廓通过四步操作:

    import cv2
    
    img = cv2.imread("example.jpg")
    img_copy = img
    
    # 灰度处理
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 平滑操作,去除噪声
    img_blur = cv2.medianBlur(img_gray, 5)
    # 通过阈值提取轮廓
    img_edge = cv2.adaptiveThreshold(img_blur,
                                     255,
                                     cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                     cv2.THRESH_BINARY,
                                     blockSize=9,
                                     C=3)
    # 将灰度图片变成 3 通道,用于后续合并
    img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2BGR)
    

    这里通过二值化的方式将轮廓提取出来,采用自适应阈值二值化函数,基于像素周围的小区域确定像素的阈值,可以将有区别的部分的界限提取出来,恰如漫画对象中黑色粗体轮廓,且细节得当。因阈值处理只能针对灰度图像,因此需要先将彩色图像转换为单通道的灰度图像,且为了去除描绘对象内部的冗余细节,还要对图像进行平滑处理,使颜色过度得缓慢一些,毕竟漫画中颜色的应用没有现实生活中那么复杂,这样得出的轮廓就比较好。

    看一下效果:
    在这里插入图片描述
    对比原图:
    在这里插入图片描述
    将两个重要的方法介绍一下:

    中值滤波:cv2.medianBlur(img, ksize)
    主要是后面的参数,代表内核区域的边长,必须是大于1的奇数,如3、5、7……方法提取内核区域下所有像素的中值,并将中心元素替换为该中值

    自适应阈值二值化:cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)

    • src: 输入图,只能输入单通道图像,通常来说为灰度图
    • dst: 输出图
    • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
    • thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.
    • type:二值化操作的类型,与固定阈值函数相同,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV.
    • Block Size: 图片中分块的大小
    • C :阈值计算方法中的常数项

    颜色填充

    边缘轮廓已经描绘好了,再添加颜料后就完整了。这里就比较简单了,只需要将原图片的颜色细致度降低些就行了。

    代码如下:

    for _ in range(2)
    	# 降低分辨率
        img_copy = cv2.pyrDown(img_copy)
    for _ in range(5):
    	# 图像平滑,保留边缘
        img_copy = cv2.bilateralFilter(img_copy, d=9, sigmaColor=9, sigmaSpace=7)
    img_copy = cv2.resize(img_copy, (img.shape[1], img.shape[0]),
                           interpolation=cv2.INTER_CUBIC)
    

    颜色要比较平滑,不能像现实生活中这么细致,先采用图像金字塔将分辨率降低,并采用双边滤波去除噪声,可以平滑平面区域,同时保持边缘清晰。分辨率降低后图像会变小,因此最后要将图像放大为原来的大小,虽然图像金字塔有专门的方法可以将图像放大,但是尺寸可能会有一两点变化,合并过程中要两个图像完全一样大,所以这里直接按尺寸放大。

    看一下效果:
    在这里插入图片描述

    将两个重要的方法介绍一下:

    分辨率降低:cv2.pyrDown(src, dst=None, dstsize=None, borderType=None)
    一般只需要输入图像就行了,它会直接将图像长宽减半

    双边滤波:cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])

    • src:输入图像
    • d:过滤时周围每个像素领域的直径
    • sigmaColor:在color space中过滤sigma。参数越大,临近像素将会在越远的地方mix。
    • sigmaSpace:在coordinate space中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。

    合并

    img_cartoon = cv2.bitwise_and(img_copy, img_edge)
    cv2.imshow("cartoon", img_cartoon)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    cv2.bitwise_and() 是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作:1&1=1,1&0=0,0&1=0,0&0=0

    最后结果:
    在这里插入图片描述

    展开全文
  • openCV 和GDI线效率对比

    千次阅读 2014-07-23 13:49:19
    由于项目需要,原来用GDI做的线的功能,新的项目中考虑到垮平台的问题,打算用openCV来实现,故此做个效率对比。 二、 2点做一条线,来测试效率。 用了同样的画板大小---256*256的大小,函数通过参数输入,用...

    一、

    由于项目需要,原来用GDI做的画线的功能,新的项目中考虑到垮平台的问题,打算用openCV来实现,故此做个效率对比。

    二、

    2点做一条线,来测试效率。

    用了同样的画板大小---256*256的大小,函数通过参数输入,用GetTickCount来实现计时功能。

    三、

    GDI的主要循代码如下:

    void  show_line(int line_num,int point_num)
    {
    
    	ULONAG start_time = get_tick_count();
    	VMGdiPolygon* test_polygon = new VMGdiPolygon();
    	int width = 256;
    	int height = 256;
    	test_polygon->VMIsCleanCloth();
    	test_polygon->VMGdiInitBuf(width,height);
    	COLORREF color = 0x0000FF;
    	test_polygon->VMGdiSetPenColor(color);
    	test_polygon->VMGdiSetPenWidth(2);
    
    	int rangle = width;
    	int line_count = line_num;	
    	for (int i = 0; i < line_count;i++)
    	{
    		for (int j = 0; j<point_num;j++)
    		{
    			int x_1 = random_fun(rangle);
    			int y_1 = random_fun(rangle);
    			
    			int x_2 = random_fun(rangle);
    			int y_2 = random_fun(rangle);			
    
    			double  pt_0[3] = {x_1,y_1,0};
    			double  pt_2[3] = {x_2,y_2,0};
    			test_polygon->VMGdiLine(pt_0,pt_2);
    		}
    		//test_polygon->VMGdiLine(data,point_num,false);
    	}
    
    	ULONAG end_time = get_tick_count();
    	cout<<"start time"<<start_time<<"--->end time:"<<end_time<<endl;
    	cout<<"the number of "<<line_count<<"  lines "<<"has "<<point_num<<" 个数"<<" takes "<<end_time-start_time<<"ms "<<endl;
    
    
    	test_polygon->VMGdiGetbitmap("D:\\001.bmp");
    }

    OpenCV的测试循环代码为:

    void test_line(int width,int height,int line_count,int point_num,int line_width)
    {
    	ULONAG start_time = get_tick_count();
    	int pic_width = width;
    	int pic_height = height;
    	Mat picture(pic_width,pic_height,CV_8UC4,Scalar(255,255,255));
    
    	int rangle = width;
    	for (int i = 0; i < line_count;i++)
    	{
    		for (int j = 0; j<point_num;j++)
    		{
    			int x_1 = random_fun(rangle);
    			int y_1 = random_fun(rangle);
    
    			int x_2 = random_fun(rangle);
    			int y_2 = random_fun(rangle);
    			//画线
    			Point a = Point (x_1,y_1);
    			Point center = Point(x_2,y_2);
    			//cout<<x_1<<"  "<<y_1<<endl;
    			//参数为:承载的图像、起始点、结束点、颜色、粗细、线型
    			line(picture,a,center,Scalar(255,0,0),line_width,8);
    		}
    	}
    
    	ULONAG end_time = get_tick_count();
    	cout<<"the number of "<<line_count<<"  lines "<<" takes "<<end_time-start_time<<"ms "<<endl;
    
    	imshow("底板",picture);
    	show_info(picture);
    }

    四、

    调用过程有在main函数中设计线的条数和每条线点的格式。


    时间对比:


    生成的图表为:

    结果对比:opencv的画线效率和GDI在1000个点的处理效率是一致的,用gettickcount使用时间的忽略不计的。

    而在整体效率比较中,很明显opencv的画线效率更高。

    五、

    两种情况均保存成bmp格式图像。

    效果对比:

    GDI效果:

    OpenCV效果:


    放大效果:

    GDI效果:

    OpenCV放大:

    目前看来,opencv 处理效果较好点。

    六、

    两个main函数的代码

    GDI main函数代码:

    #include "VMGdiPolygon.h"
    using namespace VRMap;
    
    #include <iostream>
    using namespace std;
    #include "rw_timer.h"
    
    
    int  random_fun(int rangle);
    void show_2_point_line();
    void  show_line(int line_num,int point_num,int line_width);
    //void  show_polygonline(int line_num,int point_num,int line_width);
    
    void main()
    {
    	//show_2_point_line();
    	int line_number = 1;
    	int point_numb = 10;
    	int line_width = 2;
    	show_line(line_number,point_numb);
    	//show_polygonline(line_number,point_numb,line_width);
    	system("pause");
    	return;
    }
    
    int  random_fun(int rangle)
    {
    	int seed(0);
    	int result = rand()%rangle;
    	return result;
    }
    
    void show_2_point_line()
    {
    	VMGdiPolygon* test_polygon = new VMGdiPolygon();
    	int width = 256;
    	int height = 256;	
    	test_polygon->VMIsCleanCloth();
    	test_polygon->VMGdiInitBuf(width,height);
    
    	double  pt_0[3] = {0,0,0};
    	double  pt_2[3] = {20,20,0};
    
    	COLORREF color = 0xFFFF00;
    	test_polygon->VMGdiSetPenColor(color);
    	test_polygon->VMGdiSetPenWidth(2);
    	test_polygon->VMGdiLine(pt_0,pt_2);
    
    	test_polygon->VMGdiGetbitmap("D:\\001.bmp");
    }
    
    void  show_line(int line_num,int point_num)
    {
    
    	ULONAG start_time = get_tick_count();
    	VMGdiPolygon* test_polygon = new VMGdiPolygon();
    	int width = 256;
    	int height = 256;
    	test_polygon->VMIsCleanCloth();
    	test_polygon->VMGdiInitBuf(width,height);
    	COLORREF color = 0x0000FF;
    	test_polygon->VMGdiSetPenColor(color);
    	test_polygon->VMGdiSetPenWidth(2);
    
    	int rangle = width;
    	int line_count = line_num;	
    	for (int i = 0; i < line_count;i++)
    	{
    		for (int j = 0; j<point_num;j++)
    		{
    			int x_1 = random_fun(rangle);
    			int y_1 = random_fun(rangle);
    			
    			int x_2 = random_fun(rangle);
    			int y_2 = random_fun(rangle);			
    
    			double  pt_0[3] = {x_1,y_1,0};
    			double  pt_2[3] = {x_2,y_2,0};
    			test_polygon->VMGdiLine(pt_0,pt_2);
    		}
    		//test_polygon->VMGdiLine(data,point_num,false);
    	}
    
    	ULONAG end_time = get_tick_count();
    	cout<<"start time"<<start_time<<"--->end time:"<<end_time<<endl;
    	cout<<"the number of "<<line_count<<"  lines "<<"has "<<point_num<<" 个数"<<" takes "<<end_time-start_time<<"ms "<<endl;
    
    
    	test_polygon->VMGdiGetbitmap("D:\\001.bmp");
    }

    openCV的main函数代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    using namespace std;
    
    #include "rw_timer.h"
    
    //
    
    #pragma comment(lib,"opencv_ml249d.lib")
    #pragma comment(lib,"opencv_calib3d249d.lib")
    #pragma comment(lib,"opencv_contrib249d.lib")
    #pragma comment(lib,"opencv_core249d.lib")
    #pragma comment(lib,"opencv_features2d249d.lib")
    #pragma comment(lib,"opencv_flann249d.lib")
    #pragma comment(lib,"opencv_gpu249d.lib")
    #pragma comment(lib,"opencv_highgui249d.lib")
    #pragma comment(lib,"opencv_imgproc249d.lib")
    #pragma comment(lib,"opencv_legacy249d.lib")
    #pragma comment(lib,"opencv_objdetect249d.lib")
    #pragma comment(lib,"opencv_ts249d.lib")
    #pragma comment(lib,"opencv_video249d.lib")
    #pragma comment(lib,"opencv_nonfree249d.lib")
    #pragma comment(lib,"opencv_ocl249d.lib")
    #pragma comment(lib,"opencv_photo249d.lib")
    #pragma comment(lib,"opencv_stitching249d.lib")
    #pragma comment(lib,"opencv_superres249d.lib")
    #pragma comment(lib,"opencv_videostab249d.lib")
    
    #pragma comment(lib,"opencv_objdetect249.lib")
    #pragma comment(lib,"opencv_ts249.lib")
    #pragma comment(lib,"opencv_video249.lib")
    #pragma comment(lib,"opencv_nonfree249.lib")
    #pragma comment(lib,"opencv_ocl249.lib")
    #pragma comment(lib,"opencv_photo249.lib")
    #pragma comment(lib,"opencv_stitching249.lib")
    #pragma comment(lib,"opencv_superres249.lib")
    #pragma comment(lib,"opencv_videostab249.lib")
    #pragma comment(lib,"opencv_calib3d249.lib")
    #pragma comment(lib,"opencv_contrib249.lib")
    #pragma comment(lib,"opencv_core249.lib")
    #pragma comment(lib,"opencv_features2d249.lib")
    #pragma comment(lib,"opencv_flann249.lib")
    #pragma comment(lib,"opencv_gpu249.lib")
    #pragma comment(lib,"opencv_highgui249.lib")
    #pragma comment(lib,"opencv_imgproc249.lib")
    #pragma comment(lib,"opencv_legacy249.lib")
    #pragma comment(lib,"opencv_ml249.lib")
    
    #include<iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    using namespace cv;
    
    int  random_fun(int rangle);
    void show_info(Mat picture);
    void test_line(int width,int height,int line_count,int point_num,int line_width);
    void test_polyline(int width,int height,int line_count,int point_num,int line_width);
    
    int main()
    {	
    	int width = 256;
    	int height = 256;
    
    	int line_count = 100;
    	int point_num = 1000;
    	int line_width = 1;
    	
    	test_line(width,height,line_count,point_num,line_width);
    	//
    	//test_polyline(width,height,line_count,100,line_width);
    
    	// 等待6000 ms后窗口自动关闭
    	waitKey(12000);
    }
    
    
    void show_info(Mat picture)
    {
    	if (picture.data == NULL){
    		return;
    	}
    	//IplImage* test_img = cvSaveImage()
    	int channels = picture.channels();
    	int rows = picture.rows;
    	int cols = picture.cols;
    	uchar* data = picture.data;
    	cout<<"chanels:"<<channels<<" rows:" <<rows<<" cols:"<<cols<<endl;
    }
    
    void test_line(int width,int height,int line_count,int point_num,int line_width)
    {
    	ULONAG start_time = get_tick_count();
    	int pic_width = width;
    	int pic_height = height;
    	Mat picture(pic_width,pic_height,CV_8UC4,Scalar(255,255,255));
    
    	int rangle = width;
    	for (int i = 0; i < line_count;i++)
    	{
    		for (int j = 0; j<point_num;j++)
    		{
    			int x_1 = random_fun(rangle);
    			int y_1 = random_fun(rangle);
    
    			int x_2 = random_fun(rangle);
    			int y_2 = random_fun(rangle);
    			//画线
    			Point a = Point (x_1,y_1);
    			Point center = Point(x_2,y_2);
    			//cout<<x_1<<"  "<<y_1<<endl;
    			//参数为:承载的图像、起始点、结束点、颜色、粗细、线型
    			line(picture,a,center,Scalar(255,0,0),line_width,8);
    		}
    	}
    
    	ULONAG end_time = get_tick_count();
    	cout<<"the number of "<<line_count<<"  lines "<<" takes "<<end_time-start_time<<"ms "<<endl;
    
    	imshow("底板",picture);
    	show_info(picture);
    }
    
    // 读入一张图片(游戏原画)
    //Mat img=imread("pic.jpg");
     创建一个名为 "游戏原画"窗口
    //cvNamedWindow("游戏原画");
     在窗口中显示游戏原画
    //imshow("游戏原画",img);
    
    int  random_fun(int rangle)
    {
    	int seed(0);
    	//srand( (unsigned)time( NULL ) );
    	int result = rand()%rangle;
    	return result;
    }
    
    
    
    void test_polyline(int width,int height,int line_count,int point_num,int line_width)
    {
    	ULONAG start_time = get_tick_count();	
    	int pic_width = width;
    	int pic_height = height;
    	Mat picture(pic_width,pic_height,CV_8UC4,Scalar(255,255,255));	
    
    	line_count = 1;
    	int rangle = width;
    	Point** test_points = new Point*[line_count];	
    	int *npts = new int[line_count];	
    	for (int j = 0;j < line_count;j++)
    	{
    		Point rook_points[1][100];
    		for (int k =0;k<100;k++)
    		{
    			int x = random_fun(rangle);
    			int y = random_fun(rangle);
    			rook_points[0][j] = Point( x,y);
    		}
    		const Point* ppt[1] = { rook_points[0] };
    		int npt[] = { 100 };
    		polylines(picture,ppt,npt,1,1,CV_RGB(0,255,0),2,8,0);
    	}	
    	imshow("底板",picture);
    
    	//
    	//for (int j = 0;j < line_count;j++)
    	//{
    	//	delete []test_points[j];
    	//	test_points[j] = NULL;
    	//}
    	//delete []test_points;
    	//test_points = NULL;
    
    	ULONAG end_time = get_tick_count();
    	cout<<"the number of "<<line_count<<"  lines "<<" takes "<<end_time-start_time<<"ms "<<endl;
    	show_info(picture);
    }

    当然使用需要opencv的各种库的配置。opencv的下载和使用,可参考浅墨的http://blog.csdn.net/poem_qianmo/article/details/20911629

    opencv教程和配置设置等博客。


    源码免费下载地址:GDI测试代码

    OPENCV的画线测试代码


    -------------THE END--------------

    若有问题,请不吝赐教。



    展开全文
  • Android 三大图片缓存原理、特性对比

    千次阅读 2016-09-13 15:43:48
    Android 三大图片缓存原理、特性对比
  • 用echarts柱状对比

    2019-01-18 16:01:24
    [图片说明](https://img-ask.csdn.net/upload/201901/18/1547802607_234605.png) ![图片说明](https://img-ask.csdn.net/upload/201901/18/1547798448_217436.png) 第一张图是我做出来的 我只是希望Y轴的平分正负...
  • 图片加载框架对比分析

    千次阅读 2016-09-04 18:37:51
    Google推荐的图片加载库,专注于流畅的滚动。 1.优点  1)使用RGB_565,内存占用比Picasso小一半。  2)图片展示和页面的生命周期一致(对context有类型要求)  3)相比Picasso,Glide在缓存策略和加载GIF方面...
  • java 图片转ascii字符

    千次阅读 2018-07-05 11:11:59
    图片对比:代码如下:package com.isec.dataAnalysis.tools; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; public class AsciiPic { ...
  • 今天小编就为大家分享一篇用openCV和Python 实现图片对比,并标识出不同点的方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • Java+OpenCV图片对比

    万次阅读 热门讨论 2018-07-19 14:33:08
    近期老板让研究一下航拍、遥感影像对比功能,个人认为可行性并不高,没有知识储备,而且真要做好的话得当作产品去砸钱(老板:砸钱是不可能的,这辈子都不可能砸钱)。 经过查询相关资料,OpenCV对图像的处理还是挺...
  • 项目中用gif图片来实现的话,在图片大小和动画帧数之间很难权衡。而且会导致内存吃紧。 一般Gif或者帧动画 的性能差是由于图过多,每秒种几十帧,每一帧都是一张图。一个小动画往往需要几十张图。如果变成资源...
  • 选项:亮度、对比度、高亮度、GAMMA校正、曲线、尺寸大小缩放、JPG压缩比、红蓝互换、加粗、左旋、右旋、颠倒、锐化、柔化、彩色漫画、黑白漫画、保持原样、256级、16级灰度、8级灰度、4级态度、自动色阶、自动对比...
  • 第三方图片加载框架对比分析

    千次阅读 2016-02-18 21:32:35
    glideGoogle推荐的图片加载库,专注于流畅的滚动。1.优点 1)使用RGB_565,内存占用比Picasso小一半。 2)图片展示和页面的生命周期一致(对context有类型要求) 3)相比Picasso,Glide在缓存策略和加载GIF方面...
  • 如何完成两幅图片差异对比

    千次阅读 2015-05-10 16:55:05
    因此不能直接对图片对比。请教一对比算法,最好可以调节差异灵敏度! 转成灰度图再求。  nGray=0.299*R+0.587*G+0.114*B  对每个象素用这个公式求灰度,然后对两幅图的每个象素做如下处理。  Sigma(2*A*B)/...
  • 属性动画、帧动画、补间动画的介绍使用及对比版权声明:转载必须注明本文转自南轩的博客: http://blog.csdn.net/nanxuan521 在android开发中经常会碰到一些动画需求,其中一部分动画依靠android SDK中自带的...
  • OpenCV for Unity(2.32)插件中的MatchShapesExample案例(Unity2018.2.6f1) 位置:OpenCVForUnity\Examples\MainModules\...2 导入对比图形图片 3 描边对比图片的轮廓 4 对比两张图片轮廓获取数据 一、...
  • 软件介绍: 一款能够将各种图片转换成ASCII字符的小工具,这种字符常用于论坛个性签名,如果你想让自己的...可设置图片的色阶及亮度对比度,抖动及随机量。可生成彩色字符及渐变效果。字符的范围可以自己定义。
  • 使用多张图片做帧动画的性能优化

    千次阅读 2017-06-09 18:00:09
    QQ群的送礼物功能需要加载几十张图然后做帧动画,但是多张图片加载造成了非常大的性能开销,导致图片开始加载到真正播放动画的时间间隔比较长。所以需要研究一些优化方案提升加载图片和帧动画的性能。 原理分析 ...
  • 像素对比两张图片相似度是否一样

    万次阅读 2017-06-23 16:04:49
    返回值是 'image1' 和 'image2'对比后的相似度,相似度越高,图片越接近,达到100.0说明图片完全相同。 ''' img1 = image1.resize(size).convert("RGB") sub_image1 = split_image(img1, part_size) img2 = ...
  • Python-Opencv中用compareHist函数进行直方图比较进而对比图片 图像直方图 图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的。纵坐标代表了每一种颜色值在...
  • 我所用过能工作流的工具有2个:1.eclipse插件,2.flowable官方网页版,结论是eclipse插件好用,后者要上传下载,还容易丢数据 注意事项:eclipse插件出来的bpmn文件的schama是activiti,不要改为flowable的,...
  • PNG,JPEG,BMP,JIF图片格式详解及其对比

    万次阅读 2016-08-25 00:19:52
    图片格式详解不知道大家有没有注意过网页里,手机里,平板里的图片,事实上,图片格式多样,不同平台对不同格式的图片支持也不一样,所以需要根据不同场合,使用不同格式的图片。一.PNG格式便携式网络图形(Portable...
  • 首先上个最新的Android分辨率统计的图: ...从上图我们通过计算可以得出,目前的设备前四个占据大份额(77.6%)的分辨率的手机的屏幕长宽都是按照比例缩放的。...1.Android系统的图片寻找机制对放在x
  • 前几周做了一个医疗展示CT图的项目,需要对DICOM文件进行解析展示并且在页面中对图像进行明暗和对比度的...由于要对图片进行操作(明暗及对比度的调节、反色)所以页面中使用img元素是不合适的,而HTML5中提供的can...
  • 如果您只是来看标注框的话 也只需要看这一篇文章即可,会有一个很详细的介绍和使用,但是你如果想学习整体的预处理请您看我的上一篇博文 《TensorFlow学习笔记》对图片数据的预处理一、-编码解码调整大小色彩...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 63,836
精华内容 25,534
关键字:

对比画图片