美文网首页
PHP自动识别背景并替换为透明,PHP抠图

PHP自动识别背景并替换为透明,PHP抠图

作者: _WhatsUp_ | 来源:发表于2018-03-31 20:15 被阅读0次

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Photo extends CQ_Controller {

    public function __construct()
    {
        parent::__construct();
    }

    //自动将图片背景替换为透明
    public function remove_bgcolor()
    {

        $img_name = $this->input->get_post('img','');//原图地址,如:"tp/test.jpg"
        $rongcha = $this->input->get_post('rongcha','');//容差如:50

        if(empty($rongcha))
        {
            $rongcha = 30;
        }

        if(!empty($img_name))
        {

            //获取计算出来的背景平均rgb
            $bg_rgb = $this->get_bg_rgb($img_name);
            $bg_rgb_r = $bg_rgb["r"];
            $bg_rgb_g = $bg_rgb["g"];
            $bg_rgb_b = $bg_rgb["b"];

            //获取图片
//          $src_img = $this->imagesources($img_name);

            //先等比缩放图片,否则处理时间过长
            $src_img = $this->scalePic($img_name,400,400);

            //获取图片宽高
            $src_w = imagesx($src_img);
            $src_h = imagesy($src_img);

            //创建一个原图大小的真彩图
            $target_img = imagecreatetruecolor($src_w, $src_h);

            //将原图放入真彩图
            imagecopymerge($target_img,$src_img,0,0,0,0,$src_w,$src_h,100);

            $color = imagecolorallocate($target_img, 255, 255, 255);

            //循环图片每一个像素点,将平均rgb容差范围内的点都替换为纯白色
            for($x = 0; $x < $src_w; $x++)
            {
                for($y = 0; $y < $src_h; $y++)
                {
                    $rgb = imagecolorat($src_img, $x, $y);
                    $r = ($rgb >> 16) & 0xFF;
                    $g = ($rgb >> 8) & 0xFF;
                    $b = $rgb & 0xFF;

                    if(abs($r-$bg_rgb_r)<$rongcha && abs($g-$bg_rgb_g)<$rongcha && abs($b-$bg_rgb_b)<$rongcha)
                    {
                        imagesetpixel($target_img, $x, $y, $color);//替换为纯白色
                    }
                }
            }

            imagecolortransparent($target_img, $color);

            //输出
            header("Content-Type:image/png");
            imagepng($target_img);

            //销毁
            imagedestroy($target_img);
            imagedestroy($src_img);

        }
        else
        {
            echo "请传入照片地址";
        }

    }


    //获取图片类型并打开图像资源
    function imagesources($imgad) {
        $imagearray = getimagesize( $imgad );
        switch ($imagearray [2]) {
            case 1 : // gif
                $img = imagecreatefromgif ( $imgad );
                break;
            case 2 : // jpeg
                $img = imagecreatefromjpeg ( $imgad );
                break;
            case 3 : // png
                $img = imagecreatefrompng ( $imgad );
                break;
            default :
                return false;
        }
        return $img;
    }

    //等比缩放图片
    function scalePic($img_name, $maxX=100, $maxY=100)
    {
        $info = getimagesize($img_name); //获取图片的基本信息
        $width = $info[0];//获取宽度
        $height = $info[1];//获取高度
        //判断图片资源类型并创建对应图片资源
        $im = $this->imagesources($img_name);
        //计算缩放比例
        $scale = ($maxX/$width)>($maxY/$height)?$maxY/$height:$maxX/$width;

        if ($width > $maxX || $height > $maxY)
        {
            //计算缩放后的尺寸
            $sWidth = floor($width*$scale);
            $sHeight = floor($height*$scale);
        }
        else
        {
            $sWidth = $width;
            $sHeight = $height;
        }

        //创建目标图像资源
        $nim = imagecreatetruecolor($sWidth,$sHeight);
        //等比缩放
        imagecopyresampled($nim,$im,0,0,0,0,$sWidth,$sHeight,$width,$height);
        //释放图片资源
        imagedestroy($im);
        return $nim;
    }


    //获取背景颜色,原理:先获取图片宽高,除以想要获取多少个点,获取点位间隔,然后for循环点位,取得所有点位的r、g、b分别放入各自数组,然后对每个数组排序,再从每个数组最中间取出1/3个值(因为刨去比较大的和比较小的,中间剩下的基本上就是最多的背景色),最后计算平均数,得到rgb平均值
    public function get_bg_rgb($img_name)
    {

        $point_num = 10;//横竖分别取多少个点

        $img = $this->imagesources($img_name);

        $src_info   = getimagesize($img_name);
        $src_w  = $src_info[0];
        $src_h = $src_info[1];

        $w_step = intval($src_w/($point_num+1));
        $h_step = intval($src_h/($point_num+1));

        $r = array();
        $g = array();
        $b = array();

        for($i=1;$i<=$point_num;$i++)
        {
            for($j=1;$j<=$point_num;$j++)
            {

                $rgb = ImageColorAt($img, $w_step*$i, $h_step*$j);
                $r[] = ($rgb >> 16) & 0xFF;
                $g[] = ($rgb >> 8) & 0xFF;
                $b[] = $rgb & 0xFF;

            }
        }

        //排序
        sort($r);
        sort($g);
        sort($b);

        $denominator = 3;//取出中间多少分之一个值

        $slice_offset = (($point_num*$point_num)/2)-(($point_num*$point_num/$denominator)/2);
        $slice_length = $point_num*$point_num/$denominator;
        $r = array_slice($r, $slice_offset , $slice_length);
        $g = array_slice($g, $slice_offset , $slice_length);
        $b = array_slice($b, $slice_offset , $slice_length);


        $rgb = array();
        $rgb['r'] = intval(array_sum($r)/count($r));//取平均数
        $rgb['g'] = intval(array_sum($g)/count($g));
        $rgb['b'] = intval(array_sum($b)/count($b));

        imagedestroy($img);
        return $rgb;
    }


}


相关文章

网友评论

      本文标题:PHP自动识别背景并替换为透明,PHP抠图

      本文链接:https://www.haomeiwen.com/subject/htdncftx.html