关于#php#的问题:如何用php代码实现两个图片之间的细节差异,不同点展示,图片叠加差异
细节差异部分:
class State
{
private $width;
private $height;
private $map = [];
public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
}
}
private static function createImage($path)
{
$image = null;
$info = getimagesize($path);
$type = $info[2];
if ($type == IMAGETYPE_JPEG) {
$image = imagecreatefromjpeg($path);
}
if ($type == IMAGETYPE_GIF) {
$image = imagecreatefromgif($path);
}
if ($type == IMAGETYPE_PNG) {
$image = imagecreatefrompng($path);
}
if (!$image) {
throw new InvalidArgumentException("image invalid");
}
return $image;
}
public static function fromImage($path)
{
if (!file_exists($path)) {
throw new InvalidArgumentException("image not found");
}
$image = static::createImage($path);
$width = imagesx($image);
$height = imagesy($image);
$map = [];
for ($y = 0; $y < $height; $y++) {
$map[$y] = [];
for ($x = 0; $x < $width; $x++) {
$color = imagecolorat($image, $x, $y);
$map[$y][$x] = [
"r" => ($color >> 16) & 0xFF,
"g" => ($color >> 8) & 0xFF,
"b" => $color & 0xFF
];
}
}
$new = new static($width, $height);
$new->map = $map;
return $new;
}
public function withDifference(State $state, callable $method)
{
$map = [];
for ($y = 0; $y < $this->height; $y++) {
$map[$y] = [];
for ($x = 0; $x < $this->width; $x++) {
$map[$y][$x] = $method(
$this->map[$y][$x],
$state->map[$y][$x]
);
}
}
return $this->cloneWith("map", $map);
}
private function cloneWith($property, $value)
{
$clone = clone $this;
$clone->$property = $value;
return $clone;
}
class EuclideanDistance
{
public function __invoke(array $p, array $q)
{
$r = $p["r"] - $q["r"];
$r *= $r;
$g = $p["g"] - $q["g"];
$g *= $g;
$b = $p["b"] - $q["b"];
$b *= $b;
return sqrt($r + $g + $b);
}
}
$state1 = State::fromImage("/path/to/image1.png");
$state2 = State::fromImage("/path/to/image2.png");
$state3 = $state1->withDifference(
$state2,
new EuclideanDistance()
);
让两张图片重叠的部分:
header(‘content-type:image/jpeg‘);#图片显示
$bg_width = $bg_height = 600;
#创建真彩色画布并填补灰色
$final_srouce = imagecreatetruecolor($bg_width,$bg_height);
$background_color = imagecolorAllocate($final_srouce,255,255,255);#白色底色
imagefill($final_srouce,0,0,$background_color);
#获取覆盖图片 大小为121*75
$source = ‘/Users/haodaquan/Sites/PyWeb/CoreImage/newImage/new_image.jpg‘;
$img_source = imagecreatefromjpeg($source);
$info = getimagesize($source);
######################
#1、直接覆盖图片加到画布上
#前两个数字为画布起始xy坐标,中间两个数字为覆盖图片的起始xy坐标,最后两个数字表示覆盖图片的xy长度
#imagecopy($final_srouce,$img_source,30,50,0,0,121,75);
#新图宽度留白,高度留白
$blank_width = 30;
$blank_height = 50;
#假设宽度优先填满新图,宽度大于高度的图
#计算缩放比率
$new_width = $bg_width-2*$blank_width;
$new_height = $info[1]*($new_width/$info[0]);
#2、带缩放的叠加 详见底部函数注释
imagecopyresampled($final_srouce,$img_source,$blank_width,$blank_height,0,0,$new_width,$new_height,$info[0],$info[1]);
######################
imagejpeg($final_srouce, ‘./tmp/final_srouce.jpeg‘,100);#生成图片 第三个参数为质量[1-100]
imagejpeg($final_srouce); #页面显示图片
#销毁资源
imagedestroy($final_srouce);
imagedestroy($img_source);
// bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
// $dst_image:新建的图片
// $src_image:需要载入的图片
// $dst_x:设定需要载入的图片在新图中的x坐标
// $dst_y:设定需要载入的图片在新图中的y坐标
// $src_x:设定载入图片要载入的区域x坐标
// $src_y:设定载入图片要载入的区域y坐标
// $dst_w:设定载入的原图的宽度(在此设置缩放)
// $dst_h:设定载入的原图的高度(在此设置缩放)
// $src_w:原图要载入的宽度
// $src_h:原图要载入的高度
<?php
/*已知问题:1.在图片缩放功能中,使用imagecreatetruecolor函数创建画布,并使用透明处理算法,但PNG格式的图片无法透明。用imagecreate函数创建画布可以解决这个问题,但是缩放出来的图片色数太少了
*
*
*type值:
* (1):代表使用图片缩放功能,此时,$value1代表缩放后图片的宽度,$value2代表缩放后图片的高度
* (2):代表使用图片裁剪功能,此时,$value1代表裁剪开始点的坐标,例:从原点开始即是“0,0”前面是x轴后面是y轴,中间用,分隔,$value2代表裁剪的宽度和高度,同样也是“20,20”的形式使用
* (3):代表使用加图片水印功能,此时,$value1代表水印图片的文件名,$value2代表水印在图片中的位置,有10值个可以选,1代表左上,2代表左中,3代表左右,4代表中左,5代表中中,6代表中右,7代表下做,8代表下中,9代表下右,0代表随机位置
*
*/
class image{
private $types; //使用的功能编号,1为图片缩放功能 2为图片裁剪功能 3,为图片加图片水印功能
private $imgtype;//图片的格式
private $image; //图片资源
private $width;//图片宽度
private $height;//图片高度
private $value1;//根据所传type值的不同,$value1分别代表不同的值
private $value2;//根据所传type值的不同,$value2分别代表不同的值
private $endaddress;//输出后的地址+文件名
function __construct($imageaddress, $types, $value1="", $value2="", $endaddress){
$this->types=$types;
$this->image=$this->imagesources($imageaddress);
$this->width=$this->imagesizex();
$this->height=$this->imagesizey();
$this->value1=$value1;
$this->value2=$value2;
$this->endaddress=$endaddress;
}
function outimage(){ //根据传入type值的不同,输出不同的功能
switch($this->types){
case 1:
$this->scaling();
break;
case 2:
$this->clipping();
break;
case 3:
$this->imagewater();
break;
default:
return false;
}
}
private function imagewater(){ //http://www.hzhuti.com 加图片水印功能
//用函数获取水印文件的长和宽
$imagearrs=$this->getimagearr($this->value1);
//调用函数计算出水印加载的位置
$positionarr=$this->position($this->value2, $imagearrs[0], $imagearrs[1]);
//加水印
imagecopy($this->image, $this->imagesources($this->value1), $positionarr[0], $positionarr[1], 0, 0, $imagearrs[0], $imagearrs[1]);
//调用输出方法保存
$this->output($this->image);
}
private function clipping(){ //图片裁剪功能
//将传进来的值分别赋给变量
list($src_x, $src_y)=explode(",", $this->value1);
list($dst_w, $dst_h)=explode(",", $this->value2);
if($this->width < $src_x+$dst_w || $this->height < $src_y+$dst_h){ //这个判断就是限制不能截取到图片外面去
return false;
}
//创建新的画布资源
$newimg=imagecreatetruecolor($dst_w, $dst_h);
//进行裁剪
imagecopyresampled($newimg, $this->image, 0, 0, $src_x, $src_y, $dst_w, $dst_h, $dst_w, $dst_h);
//调用输出方法保存
$this->output($newimg);
}
private function scaling(){ //图片缩放功能
//获取等比缩放的宽和高
$this-> proimagesize();
//根据参数进行缩放,并调用输出函数保存处理后的文件
$this->output($this->imagescaling());
}
private function imagesources($imgad){ //获取图片类型并打开图像资源
$imagearray=$this->getimagearr($imgad);
switch($imagearray[2]){
case 1://gif
$this->imgtype=1;
$img=imagecreatefromgif($imgad);
break;
case 2://jpeg
$this->imgtype=2;
$img=imagecreatefromjpeg($imgad);
break;
case 3://png
$this->imgtype=3;
$img=imagecreatefrompng($imgad);
break;
default:
return false;
}
return $img;
}
private function imagesizex(){ //获得图片宽度
return imagesx($this->image);
}
private function imagesizey(){ //获取图片高度
return imagesy($this->image);
}
private function proimagesize(){ //计算等比缩放的图片的宽和高
if($this->value1 && ($this->width < $this->height)) { //等比缩放算法
$this->value1=round(($this->value2/ $this->height)*$this->width);
}else{
$this->value2=round(($this->value1/ $this->width) * $this->height);
}
}
private function imagescaling(){//图像缩放功能,返回处理后的图像资源
$newimg=imagecreatetruecolor($this->value1, $this->value2);
$tran=imagecolortransparent($this->image);//处理透明算法
if($tran >= 0 && $tran < imagecolorstotal($this->image)){
$tranarr=imagecolorsforindex($this->image, $tran);
$newcolor=imagecolorallocate($newimg, $tranarr['red'], $tranarr['green'], $tranarr['blue']);
imagefill($newimg, 0, 0, $newcolor);
imagecolortransparent($newimg, $newcolor);
}
imagecopyresampled($newimg, $this->image, 0, 0, 0, 0, $this->value1, $this->value2, $this->width, $this->height);
return $newimg;
}
private function output($image){//输出图像
switch($this->imgtype){
case 1:
imagegif($image, $this->endaddress);
break;
case 2:
imagejpeg($image, $this->endaddress);
break;
case 3:
imagepng($image, $this->endaddress);
break;
default:
return false;
}
}
private function getimagearr($imagesou){//返回图像属性数组方法
return getimagesize($imagesou);
}
private function position($num, $width, $height){//根据传入的数字返回一个位置的坐标,$width和$height分别代表插入图像的宽和高
switch($num){
case 1:
$positionarr[0]=0;
$positionarr[1]=0;
break;
case 2:
$positionarr[0]=($this->width-$width)/2;
$positionarr[1]=0;
break;
case 3:
$positionarr[0]=$this->width-$width;
$positionarr[1]=0;
break;
case 4:
$positionarr[0]=0;
$positionarr[1]=($this->height-$height)/2;
break;
case 5:
$positionarr[0]=($this->width-$width)/2;
$positionarr[1]=($this->height-$height)/2;
break;
case 6:
$positionarr[0]=$this->width-$width;
$positionarr[1]=($this->height-$height)/2;
break;
case 7:
$positionarr[0]=0;
$positionarr[1]=$this->height-$height;
break;
case 8:
$positionarr[0]=($this->width-$width)/2;
$positionarr[1]=$this->height-$height;
break;
case 9:
$positionarr[0]=$this->width-$width;
$positionarr[1]=$this->height-$height;
break;
case 0:
$positionarr[0]=rand(0, $this->width-$width);
$positionarr[1]=rand(0, $this->height-$height);
break;
}
return $positionarr;
}
function __destruct(){
imagedestroy($this->image);
}
}
?>
:
/************************************************************
** @Description: 图片叠加demo
** @Author: haodaquan
** @Date: 2016-11-30 12:07:51
** @Last Modified by: haodaquan
** @Last Modified time: 2017-02-09 13:59:51
*************************************************************/
header(‘content-type:image/jpeg‘);#图片显示
$bg_width = $bg_height = 600;
#创建真彩色画布并填补灰色
$final_srouce = imagecreatetruecolor($bg_width,$bg_height);
$background_color = imagecolorAllocate($final_srouce,255,255,255);#白色底色
imagefill($final_srouce,0,0,$background_color);
#获取覆盖图片 大小为12175
$source = ‘/Users/haodaquan/Sites/PyWeb/CoreImage/newImage/new_image.jpg‘;
$img_source = imagecreatefromjpeg($source);
$info = getimagesize($source);
######################
#1、直接覆盖图片加到画布上
#前两个数字为画布起始xy坐标,中间两个数字为覆盖图片的起始xy坐标,最后两个数字表示覆盖图片的xy长度
#imagecopy($final_srouce,$img_source,30,50,0,0,121,75);
#新图宽度留白,高度留白
$blank_width = 30;
$blank_height = 50;
#假设宽度优先填满新图,宽度大于高度的图
#计算缩放比率
$new_width = $bg_width-2$blank_width;
$new_height = $info[1]*($new_width/$info[0]);
#2、带缩放的叠加 详见底部函数注释
imagecopyresampled($final_srouce,$img_source,$blank_width,$blank_height,0,0,$new_width,$new_height,$info[0],$info[1]);
######################
imagejpeg($final_srouce, ‘./tmp/final_srouce.jpeg‘,100);#生成图片 第三个参数为质量[1-100]
imagejpeg($final_srouce); #页面显示图片
#销毁资源
imagedestroy($final_srouce);
imagedestroy($img_source);
// bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
// $dst_image:新建的图片
// $src_image:需要载入的图片
// $dst_x:设定需要载入的图片在新图中的x坐标
// $dst_y:设定需要载入的图片在新图中的y坐标
// $src_x:设定载入图片要载入的区域x坐标
// $src_y:设定载入图片要载入的区域y坐标
// $dst_w:设定载入的原图的宽度(在此设置缩放)
// $dst_h:设定载入的原图的高度(在此设置缩放)
// $src_w:原图要载入的宽度
// $src_h:原图要载入的高度
<?php
/**
* 图片相似度比较
*
* @version $Id: ImageHash.php 4429 2012-04-17 13:20:31Z jax $
* @author jax.hu
*
* <code>
* //Sample_1
* $aHash = ImageHash::hashImageFile(‘wsz.11.jpg’);
* $bHash = ImageHash::hashImageFile(‘wsz.12.jpg’);
* var_dump(ImageHash::isHashSimilar($aHash, $bHash));
*
* //Sample_2
* var_dump(ImageHash::isImageFileSimilar(‘wsz.11.jpg’, ‘wsz.12.jpg’));
* </code>
*/
class ImageHash {
/**取样倍率 1~10
* @access public
* @staticvar int
* */
public static $rate = 2;
/**相似度允许值 0~64
* @access public
* @staticvar int
* */
public static $similarity = 80;
/**图片类型对应的开启函数
* @access private
* @staticvar string
* */
private static $_createFunc = array(
IMAGETYPE_GIF =>’imageCreateFromGIF’,
IMAGETYPE_JPEG =>’imageCreateFromJPEG’,
IMAGETYPE_PNG =>’imageCreateFromPNG’,
IMAGETYPE_BMP =>’imageCreateFromBMP’,
IMAGETYPE_WBMP =>’imageCreateFromWBMP’,
IMAGETYPE_XBM =>’imageCreateFromXBM’,
);
/**从文件建立图片
* @param string $filePath 文件地址路径
* @return resource 当成功开启图片则传递图片 resource ID,失败则是 false
* */
public static function createImage($filePath){
if(!file_exists($filePath)){ return false; }
/*判断文件类型是否可以开启*/
$type = exif_imagetype($filePath);
if(!array_key_exists($type,self::$_createFunc)){ return false; }
$func = self::$_createFunc[$type];
if(!function_exists($func)){ return false; }
return $func($filePath);
}
/**hash 图片
* @param resource $src 图片 resource ID
* @return string 图片 hash 值,失败则是 false
* */
public static function hashImage($src){
if(!$src){ return false; }
/*缩小图片尺寸*/
$delta = 8 * self::$rate;
$img = imageCreateTrueColor($delta,$delta);
imageCopyResized($img,$src, 0,0,0,0, $delta,$delta,imagesX($src),imagesY($src));
/*计算图片灰阶值*/
$grayArray = array();
for ($y=0; $y<$delta; $y++){
for ($x=0; $x<$delta; $x++){
$rgb = imagecolorat($img,$x,$y);
$col = imagecolorsforindex($img, $rgb);
$gray = intval(($col[‘red’]+$col[‘green’]+$col[‘blue’])/3)& 0xFF;
$grayArray[] = $gray;
}
}
imagedestroy($img);
/*计算所有像素的灰阶平均值*/
$average = array_sum($grayArray)/count($grayArray);
/*计算 hash 值*/
$hashStr = ”;
foreach ($grayArray as $gray){
$hashStr .= ($gray>=$average) ? ‘1’ : ‘0’;
}
return $hashStr;
}
/**hash 图片文件
* @param string $filePath 文件地址路径
* @return string 图片 hash 值,失败则是 false
* */
public static function hashImageFile($filePath){
$src = self::createImage($filePath);
$hashStr = self::hashImage($src);
imagedestroy($src);
return $hashStr;
}
/**比较两个 hash 值,是不是相似
* @param string $aHash A图片的 hash 值
* @param string $bHash B图片的 hash 值
* @return bool 当图片相似则传递 true,否则是 false
* */
public static function isHashSimilar($aHash, $bHash){
$aL = strlen($aHash); $bL = strlen($bHash);
if ($aL !== $bL){ return false; }
/*计算容许落差的数量*/
$allowGap = $aL*(100-self::$similarity)/100;
/*计算两个 hash 值的汉明距离*/
$distance = 0;
for($i=0; $i<$aL; $i++){
if ($aHash{$i} !== $bHash{$i}){ $distance++; }
}
return ($distance<=$allowGap) ? true : false;
}
/**比较两个图片文件,是不是相似
* @param string $aHash A图片的路径
* @param string $bHash B图片的路径
* @return bool 当图片相似则传递 true,否则是 false
* */
public static function isImageFileSimilar($aPath, $bPath){
$aHash = ImageHash::hashImageFile($aPath);
$bHash = ImageHash::hashImageFile($bPath);
return ImageHash::isHashSimilar($aHash, $bHash);
}
}
采用帧差分法,PHP不会,给你一个可参考的C吧
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[120][120],m,n,i,j,t;
int main(void)
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(i=0;i<m;i++) scanf("%d",&a[0][i]);
//遍历到0阶的序列
for(i=1;i<m;i++)
{
for(j=0;j<m-i;j++)
a[i][j]=a[i-1][j+1]-a[i-1][j];
}
//扩展0阶序列
for(i=1;i<=n;i++) a[m-1][i]=a[m-1][0];
//依次向上求解,求出后面n个数的值
for(i=m-2;i>=0;i--)
{
for(j=m-i;j<m+n;j++)
a[i][j]=a[i][j-1]+a[i+1][j-1];
}
for(i=m;i<m+n-1;i++) printf("%d ",a[0][i]);
printf("%d\n",a[0][i]);
}
return 0;
}
思路:
第一步:先查找出图像差异
https://blog.csdn.net/culi4814/article/details/108373972
第二步:再两张图片合成一个图片
https://blog.csdn.net/weixin_42963159/article/details/82688101
class State
{
private $width;
private $height;
private $map = [];
public function __construct($width, $height)
{
$this->width = $width;
$this->height = $height;
}
}
第一步-先查找出图像差异
网页:https://blog.csdn.net/culi4814/article/details/108373972
第二步-再两张图片合成一个图片
网页:https://blog.csdn.net/weixin_42963159/article/details/82688101
注:参考了上面的答案
试试这个https://blog.csdn.net/culi4814/article/details/108373972
你看行不行:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[120][120],m,n,i,j,t;
int main(void)
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(i=0;i<m;i++) scanf("%d",&a[0][i]);
//遍历到0阶的序列
for(i=1;i<m;i++)
{
for(j=0;j<m-i;j++)
a[i][j]=a[i-1][j+1]-a[i-1][j];
}
//扩展0阶序列
for(i=1;i<=n;i++) a[m-1][i]=a[m-1][0];
//依次向上求解,求出后面n个数的值
for(i=m-2;i>=0;i--)
{
for(j=m-i;j<m+n;j++)
a[i][j]=a[i][j-1]+a[i+1][j-1];
}
for(i=m;i<m+n-1;i++) printf("%d ",a[0][i]);
printf("%d\n",a[0][i]);
}
return 0;
}
看下这个行不行 https://blog.csdn.net/weixin_36424234/article/details/115165338
https://www.php.cn/php-weizijiaocheng-383488.html参考一下
可以参考如下链接https://blog.csdn.net/weixin_36424234/article/details/115165338
1、直接覆盖图片加到画布上
#前两个数字为画布起始xy坐标,中间两个数字为覆盖图片的起始xy坐标,最后两个数字表示覆盖图片的xy长度
#imagecopy($final_srouce,$img_source,30,50,0,0,121,75);
#新图宽度留白,高度留白
$blank_width = 30;
$blank_height = 50;
#假设宽度优先填满新图,宽度大于高度的图
#计算缩放比率
$new_width = $bg_width-2*$blank_width;
$new_height = $info[1]*($new_width/$info[0]);
#2、带缩放的叠加 详见底部函数注释
imagecopyresampled($final_srouce,$img_source,$blank_width,$blank_height,0,0,$new_width,$new_height,$info[0],$info[1]);
######################
imagejpeg($final_srouce, ‘./tmp/final_srouce.jpeg‘,100);#生成图片 第三个参数为质量[1-100]
imagejpeg($final_srouce); #页面显示图片
#销毁资源
imagedestroy($final_srouce);
imagedestroy($img_source);
// bool imagecopyresampled ( resource $dst_image , resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h )
// $dst_image:新建的图片
// $src_image:需要载入的图片
// $dst_x:设定需要载入的图片在新图中的x坐标
// $dst_y:设定需要载入的图片在新图中的y坐标
// $src_x:设定载入图片要载入的区域x坐标
// $src_y:设定载入图片要载入的区域y坐标
// $dst_w:设定载入的原图的宽度(在此设置缩放)
// $dst_h:设定载入的原图的高度(在此设置缩放)
// $src_w:原图要载入的宽度
// $src_h:原图要载入的高度
可参考https://blog.csdn.net/culi4814/article/details/108373972,先找差异,再合成一个图片
看一下http://duoduokou.com/php/13290732320901280810.html
* //Sample_1 * $aHash = ImageHash::hashImageFile('wsz.11.jpg'); * $bHash = ImageHash::hashImageFile('wsz.12.jpg'); * var_dump(ImageHash::isHashSimilar($aHash, $bHash)); * * //Sample_2 * var_dump(ImageHash::isImageFileSimilar('wsz.11.jpg', 'wsz.12.jpg')); * */ class ImageHash { /**取样倍率 1~10 * @access public * @staticvar int * */ public static $rate = 2; /**相似度允许值 0~64 * @access public * @staticvar int * */ public static $similarity = 80; /**图片类型对应的开启函数 * @access private * @staticvar string * */ private static $_createFunc = array( IMAGETYPE_GIF =>'imageCreateFromGIF', IMAGETYPE_JPEG =>'imageCreateFromJPEG', IMAGETYPE_PNG =>'imageCreateFromPNG', IMAGETYPE_BMP =>'imageCreateFromBMP', IMAGETYPE_WBMP =>'imageCreateFromWBMP', IMAGETYPE_XBM =>'imageCreateFromXBM', ); /**从文件建立图片 * @param string $filePath 文件地址路径 * @return resource 当成功开启图片则传递图片 resource ID,失败则是 false * */ public static function createImage($filePath){ if(!file_exists($filePath)){ return false; } /*判断文件类型是否可以开启*/ $type = exif_imagetype($filePath); if(!array_key_exists($type,self::$_createFunc)){ return false; } $func = self::$_createFunc[$type]; if(!function_exists($func)){ return false; } return $func($filePath); } 这是PHP实现图像比较没有太细节