利用k-means聚类算法识别图片主色调
识别图片主色调这个,网上貌似有几种方法,不过,最准确,最优雅的解决方案还是利用聚类算法来做。。。
直接上代码。。。。不过,我测试结果表示,用PHP来做,效率不佳,PHP不适合做这种大规模运算~~~,用nodejs做 效率可以高出100倍左右。。。
代码如下 | 复制代码 |
<?php $start = microtime(TRUE); main();
function main($img = ‘colors_files/T1OX3eXldXXXcqfYM._111424.jpg’) {
list($width, $height, $mime_code) = getimagesize($img);
$im = null; $point = array(); switch ($mime_code) { # jpg case 2: $im =imagecreatefromjpeg($img); break;
# png case 3:
default: exit(‘擦 ,什么图像?解析不了啊’); }
$new_width = 100; $new_height = 100; $pixel = imagecreatetruecolor($new_width, $new_height); imagecopyresampled($pixel, $im, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
run_time();
$i = $new_width; while ($i–) { # reset高度 $k = $new_height; while ($k–) { $rgb = ImageColorAt($im, $i, $k); array_push($point, array(‘r’=>($rgb >> 16) & 0xFF, ‘g’=>($rgb >> 8) & 0xFF, ‘b’=>$rgb & 0xFF)); } } imagedestroy($im); imagedestroy($pixel);
run_time();
$color = kmeans($point);
run_time();
foreach ($color as $key => $value) &nb echo ‘<br><span style=“background-color:’ . RGBToHex($value[0]) . ‘” >’ . RGBToHex($value[0]) . ‘</span>’; }
}
function run_time() { global $start; echo ‘<br/>消耗:’, microtime(TRUE) – $start; }
function kmeans($point=array(), $k=3, $min_diff=1) { global $ii; $point_len = count($point); $clusters = array(); $cache = array();
for ($i=0; $i < 256; $i++) { $cache[$i] = $i*$i; }
# 随机生成k值 $i = $k; $index = 0; while ($i–) { $index = mt_rand(1,$point_len-100); array_push($clusters, array($point[$index], array($point[$index]))); }
run_time(); $point_list = array();
$run_num = 0;
while (TRUE) { foreach ($point as $value) { $smallest_distance = 10000000;
# 求出距离最小的点 # index用于保存point最靠近的k值 $index = 0; $i = $k; while ($i–) { $distance = 0; foreach ($value as $key => $p1) { &n { $distance += $cache[$p1 - $clusters[$i][0][$key]]; } else { $distance += $cache[$clusters[$i][0][$key] – $p1]; } }
$ii++;
if ($distance < $smallest_distance) { $smallest_distance = $distance; $index = $i; } } $point_list[$index][] = $value; }
$diff = 0; # 1个1个迭代k值 $i = $k; while ($i–) { $old = $clusters[$i];
# 移到到队列中心 $center = calculateCenter($point_list[$i], 3); # 形成新的k值集合队列 $new_cluster = array($center, $point_list[$i]); $clusters[$i] = $new_cluster;
# 计算新的k值与队列所在点的位置 $diff = euclidean($old[0], $center); }
# 判断是否已足够聚合 if ($diff < $min_diff) { break; }
} echo ‘—>’.$ii;
return $clusters; }
# 计算2点距离 $ii = 0; function euclidean($p1, $p2) {
$s = 0; foreach ($p1 as $key => $value) {
$temp = ($value – $p2[$key]); $s += $temp*$temp; }
return sqrt($s);
}
# 移动k值到所有点的中心 function calculateCenter($point_list, $attr_num) { $vals = array(); $point_num = 0;
$keys = array_keys($point_list[0]); foreach($keys as $value) { $vals[$value] = 0; }
foreach ($point_list as $arr) { $point_num++; foreach ($arr as $key => $value) { $vals[$key] += $value; } }
foreach ($keys as $index) { $vals[$index] = $vals[$index] / $point_num; }
return $vals; }
function RGBToHex($r, $g=”, $b=”) { if (is_array($r)) { $b = $r['b']; $g = $r['g'];
}
$hex = “#”; $hex.= str_pad(dechex($r), 2, ’0′, STR_PAD_LEFT); $hex.= str_pad(dechex($g), 2, ’0′, STR_PAD_LEFT); $hex.= str_pad(dechex($b), 2, ’0′, STR_PAD_LEFT);
return $hex; } ?> |
主要是考虑到QQ的PHP SDK写的真是太烂了,纯属是普及API知识,而不是到手就可以部署的类库。。反正自己都写了一个了,就拿出来分享下。。
什么也不多说,直接上代码。
Qq_sdk.php
代码如下 | 复制代码 |
<?php /** * QQ开发平台 SDK * 作者:偶尔陶醉 * blog: www.stutostu.com */
class Qq_sdk{
//配置APP参数 private $app_id = 你的APP ID; private $app_secret = ‘你的APP_secret’; private $redirect = 你的回调地址;
function __construct() {
}
/** * [get_access_token 获取access_token] * @param [string] $code [登陆后返回的$_GET['code']] * @return [array] [expires_in 为有效时间 , access_token 为授权码 ; 失败返回 error , error_description ] */ function get_access_token($code) { //获取access_token $token_url = ‘https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&’ . ‘client_id=’ . $this->app_id . ‘&redirect_uri=’ . urlencode($this->redirect)//回调地址 . ‘&client_secret=’ . $this->app_secret . ‘&code=’ . $code; $token = array(); //expires_in 为access_token 有效时间增量 parse_str($this->_curl_get_content($token_url), $token);
return $token; }
/** * [get_open_id 获取用户唯一ID,openid] * @param [string] $token [授权码] * @return [array] [成功返回client_id 和 openid ;失败返回error 和 error_msg] */ function get_open_id($token) { $str = $this->_curl_get_content(‘https://graph.qq.com/oauth2.0/me?access_token=’ . $token); if (strpos($str, “callback”) !== false) { $lpos = strpos($str, “(“); $rpos = strrpos($str, “)”); $str = substr($str, $lpos + 1, $rpos – $lpos -1); } $user = json_decode($str, TRUE);
return $user; }
/** * [get_user_info 获取用户信息] * @param [string] $token [授权码] * @param [string] $open_id [用户唯一ID] * @return [array] [ret:返回码,为0时成功。msg为错误信息,正确返回时为空。...params] */ function get_user_info($token, $open_id) {
//组装URL $user_info_url = ‘https://graph.qq.com/user/get_use . ‘access_token=’ . $token . ‘&oauth_consumer_key=’ . $this->app_id . ‘&openid=’ . $open_id . ‘&format=json’;
$info = json_decode($this->_curl_get_content($user_info_url), TRUE);
return $info; }
private function _curl_get_content($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_URL, $url); //设置超时时间为3s curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 3); $result = curl_exec($ch); curl_close($ch);
return $result; }
}
/* end of Qq_sdk.php */
|
使用方法:在你网站上放置超链接,地址为:https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=你的APP_ID&redirect_uri=你的回调地址
在回调地址上调用我上面这个qq_sdk即可。
demo如下:
代码如下 | 复制代码 |
if(empty($_GET['code'])) { exit(‘参数非法’); }
include(‘qq_sdk’); $qq_sdk = new Qq_sdk(); $token = $qq_sdk->get_access_token($_GET['code']); print_r($token);
$open_id = $qq_sdk->get_open_id($token['access_token']); print_r($open_id);
$user_info = $qq_sdk->get_user_info($token['access_token'], $open_id['openid']); print_r($user_info); |
代码如下 | 复制代码 |
<?php
|
抽奖算法需要满足的需求如下:
1.可以控制中奖的概率
2.具有随机性
3.最好可以控制奖品的数量
4.根据用户ID或者ip、手机号、QQ号等条件限制抽奖次数
初期就这些需求,然后根据网上的资料,采用了一种阶段式抽取的方法,大家下面看一下整体的程序:
该程序是在ThinkPHP框架下完成的,使用了一些框架自带的类库和函数,下面我会逐一进行说明,控制器部分:
代码如下 | 复制代码 |
<?php /** * * * @lanfengye <zibin_5257@163.com> */ class ChoujiangAction extends Action { //抽奖的开始时间 var $begin_time="2012-12-25 14:00:00"; //开始时间 0-不限制 //抽奖的结束时间 var $stop_time="0"; //结束时间 0-不限制 //本次抽奖的奖项信息,必须按照从大到小的顺序进行填写,id为奖次,prize为中奖信息,v为中奖概率,num为奖品数量 //需要注意的是,该处也必须包含不中奖的信息,概率从小到大进行排序 var $prize_arr = array( '0' => array('id' => 1, 'prize' => '44元购买1G/年空间', 'v' => 1,'num'=>1), '1' => array('id' => 2, 'prize' => '55元购买1G/年空间', 'v' => 2,'num'=>2), '2' => array('id' => 3, 'prize' => '66元购买1G/年空间', 'v' => 5,'num'=>2), '3' => array('id' => 4, 'prize' => '77元购买1G/年空间', 'v' => 10,'num'=>3), '4' => array('id' => 5, 'prize' => '88元购买1G/年空间', 'v' => 15,'num'=>4), '5' => array('id' => 6, 'prize' => '99元购买1G/年空间', 'v' => 67,'num'=>10), ); //首页显示方法 public function index(){ //连接数据库,去获取本次中奖的人员名单 $Choujiang=M('Choujiang'); $this->assign('list', $Choujiang->where("rid>0")->order('id desc')->select()); unset($Choujiang); //在首页中显示抽奖的开始时间 $this->assign('begin_time',$this->begin_time); $this->display(); } /** * 生成中奖信息,ajax进行请求该方法,需要客户填写QQ号码 */ public function make() { $qq_no= trim($_POST['qq_no']); import('ORG.Util.Input'); $qq_no=Input::getVar($qq_no); if(empty($qq_no)){ $this->ajaxReturn(1, '请正确填写QQ号码!'); exit; } if(!empty($this->begin_time) && time()<strtotime($this->begin_time)){ $this->ajaxReturn(1, '抽奖还没有开始,开始时间为:'.$this->begin_time); exit; } if(!empty($this->stop_time) && time()>strtotime($this->stop_time)){ $this->ajaxReturn(1, '本次抽奖已经结束,结束时间为:'.$this->stop_time); exit; } //获取奖项信息数组,来源于私有成员 $prize_arr= $this->prize_arr; foreach ($prize_arr as $key => $val) { $arr[$val['id']] = $val['v']; } //$rid中奖的序列号码 $rid = $this->get_rand($arr); //根据概率获取奖项id $str = $prize_arr[$rid - 1]['prize']; //中奖项 $Choujiang=M('Choujiang'); //从数据库中获取特定QQ号已经参加抽奖的次数,如果大于等于3则提示次数用完 if($Choujiang->where("qq_no='{$qq_no}'")->count()>=3){ $str='您3次抽奖机会已经用完!'; $rid=0; //从数据库中获取特定奖项序号的次数,大于等于设置的最大次数则提示奖品被抽完,如果需要一直中最后一个纪念奖,则修改该处即可 }elseif ($Choujiang->where("rid={$rid}")->count()>=$prize_arr[$rid-1]['num']) { $str='很抱歉,您所抽中的奖项已经中完!'; $rid=0; } //生成一个用户抽奖的数据,用来记录到数据库 $data=array( 'rid'=>$rid, 'pop'=>$str, 'qq_no'=>$qq_no, 'input_time'=>time() ); //将用户抽奖信息数组写入数据库 $Choujiang->add($data); unset($Choujiang); //ajax返回信息 $this->ajaxReturn(1, $str); } /** * 根据概率获取中奖号码 */ private function get_rand($proArr) { $result = ''; //概率数组的总概率精度 $proSum = array_sum($proArr); //概率数组循环 foreach ($proArr as $key => $proCur) { $randNum = mt_rand(1, $proSum); if ($randNum <= $proCur) { $result = $key; break; } else { $proSum -= $proCur; } } unset($proArr); return $result; } } ?> |
该算法简单使用,并发访问性能非常好,稍加改动就可以用于各种场合,结合用户登录等信息可有效控制每个人的抽奖次数。将开始和结束之间更改为数组,就可以完善成为每天特定时间抽奖的程序。
在php中fsockopen函数可以模仿用户去访问一些网站并且还可以带一些常用的信息,如果浏览器,IP,post,get 等等数据,下面我分别一来给大家介绍介绍。如果你要使用fsockopen函数我们必须在php.ini中把allow_url_fopen = On 设置为开启状态。
例
fsockopen() Example
代码如下 | 复制代码 |
<?php |
伪造post
POST HTTP请求(URL)并获取返回值
代码如下 | 复制代码 |
<?php $srv_ip = '192.168.1.5';//你的目标服务地址. $srv_port = 80;//端口 $url = 'http://localhost/fsock.php'; //接收你post的URL具体地址 $fp = ''; $errno = 0;//错误处理 $errstr = '';//错误处理 $timeout = 10;//多久没有连上就中断 $post_str = "username=demo&password=hahaha";//要提交的内容. //打开网络的 Socket 链接。 $fp = fsockopen($srv_ip,$srv_port,$errno,$errstr,$timeout); if (!$fp){ echo('fp fail'); } $content_length = strlen($post_str); $post_header = "POST $url HTTP/1.1rn"; $post_header .= "Content-Type: application/x-www-form-urlencodedrn"; $post_header .= "User-Agent: MSIErn"; $post_header .= "Host: ".$srv_ip."rn"; $post_header .= "Content-Length: ".$content_length."rn"; $post_header .= "Connection: closernrn"; $post_header .= $post_str."rnrn"; fwrite($fp,$post_header);
$inheader = 1; while(!feof($fp)){//测试文件指针是否到了文件结束的位置 $line = fgets($fp,1024); //去掉请求包的头信息 if ($inheader && ($line == "n" || $line == "rn")) { $inheader = 0; } if ($inheader == 0) { echo $line; } } fclose($fp); unset ($line); ?> |
简要说明:代码第二行是你的IP地址或域名,第四行是你要POST的页面的具体地址,本例用的是fsock.php,fsock.php内容如下:
代码如下 | 复制代码 |
<?php echo "username:".$_POST['username']."<br/>"; echo "password:".$_POST['password']; ?>
|
结果为:
username:demo
password:hahaha
伪造get
同时伪造post,get方法。
代码如下 | 复制代码 |
<?php |
相关文章
使用PHP+JavaScript将HTML页面转换为图片的实例分享
这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19- php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
- 这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
- 今天小编在这里就来给各位Photoshop的这一款软件的使用者们来说说把古装美女图片转为细腻的工笔画效果的制作教程,各位想知道方法的使用者们,那么下面就快来跟着小编一...2016-09-14
- 这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
- 作者:Sabine 【导读】本文介绍了C#的四种排序算法:冒泡排序、选择排序、插入排序和希尔排序 冒泡排序 using System; namespace BubbleSorter { public class Bubb...2020-06-25
- 这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
- 下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮
jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮...2013-10-13- 这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
- Photoshop的这一款软件小编相信很多的人都已经是使用过了吧,那么今天小编在这里就给大家带来了用Photoshop软件制作枪战电影海报的教程,想知道制作步骤的玩家们,那么下面...2016-09-14
- 图片剪裁是常用的方法,那么如何通过4坐标剪裁图片,本文就详细的来介绍一下,感兴趣的小伙伴们可以参考一下...2021-06-04
- 共享一段使用PHP下载CSS文件中的图片的代码 复制代码 代码如下: <?php //note 设置PHP超时时间 set_time_limit(0); //note 取得样式文件内容 $styleFileContent = file_get_contents('images/style.css'); //not...2013-10-04
- 这篇文章主要给大家介绍了关于微信小程序如何获取图片宽度与高度的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-10
- PHP代码如下:复制代码 代码如下:if (isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) { $upload_file = $_FILES['Filedata']; $fil...2013-10-04
- ps软件是现在很多人比较喜欢的,有着非常不错的使用效果,这次文章就给大家介绍下ps怎么制作图片阴影效果,还不知道制作方法的赶紧来看看。 ps图片阴影效果怎么做方法/...2017-07-06
C#中图片旋转和翻转(RotateFlipType)用法分析
这篇文章主要介绍了C#中图片旋转和翻转(RotateFlipType)用法,实例分析了C#图片旋转及翻转Image.RotateFlip方法属性的常用设置技巧,需要的朋友可以参考下...2020-06-25- 这篇文章主要介绍了OpenCV如何去除图片中的阴影的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-29
- 这篇文章主要介绍了JavaScript 如何禁止用户保存图片,帮助大家完成需求,更好的理解和使用JavaScript,感兴趣的朋友可以了解下...2020-11-19
- 本文主要介绍用C#实现图片转换成字节流,字节流转换成图片,并根据图片路径返回图片的字节流,有需要的朋友可以参考下...2020-06-25