8月8号到8月18号,根据Lazysnapping的论文和一些资料,做了算法实现 但是前期处理和LS不同, 其实不算真正实现LS。
有人用通俗易懂的话这样解释:
首先,当一张图被导入到Lazy snapping中时,软件会自动采用watershed对该图进行处理。接下来,用户通过划线,确定F和B。如果从像素点的角度来看,一旦画了一条线,则这条线经过的像素点被称为“种子点”,这些“种子点”所涉及到的区域被称为“种子区域”。借助这些“种子区域”将图片分为F 和B 。利用Graph Cut优化算法,图片上所有区域会被赋予惟一的属性,不属于“前景区域”就一定会属于“背景区域”。
在经过处理后的图片中,相邻的区域连接在一起。而接下来Graph Cut优化算法要做的,就是尝试将每个非“种子区域”分别与“前景区域”(或“背景区域”)之间的通路“打断”。如果全部通路都可以被打断,则软件猜测该区域不属于F,则可能属于B。也就将我们所需要的前景的大致轮廓勾勒了出来。
Graph Cut 优化的准则,考虑了每一个区域的颜色与种子区域之间的颜色相似性,颜色越像“前景区域”就越可能被分在前景。同时它也考虑了相邻区域的颜色差别,颜色差别越大这两个区域越可能被分开。这个优化问题可以用图论中极大流(极小割)的方法很快解决。
实质上就是图像里面将问题转换成最大流最小割问题。 主要是将前景设置为sink 也就是终点, 背景设置为source 源。中间点 根据它们离前景和背景的每个像素点的颜色差值 来设置流入和流出权重,离前景越近 流入的权重越多 流出的权重越少。每条边的值 是与颜色差成反比,两个点颜色越不相似,值越小,也就是容积越小。 这个是GrabCut的本质 因为LS的关键是将Grabcut和预处理进行了很好的结合,将速度提升了。而这一步,我是没做的。
傻乎乎的写完之后 ,才弄清楚。。。。哎 回头有空用opencv里的资源再实现一次。
基本框架来自于 http://lzhj.me/archives/93 的源码,thx
他的和原文的差别主要在 GraphCut的预处理 是通过降低像素来进行,原文用了watershed来初分割。
其次,原文不是用平均距离来计算 该点到F其他点的距离,而是将F中的点进行64的kmeans聚类,然后寻找其中最小的距离点。
再次,E2的计算方法不同。
然后改进根据gimp的开源代码进行了改进 http://graphics.ethz.ch/teaching/former/imagesynthesis_06/miniprojects/p2/index.html
lzhj的程序 分割 出来会有许多零碎区域,但是如果在计算E1时,加入kmeans聚类,则 这样的 区域会减少很多。
而对E2的修正 能够 很好的提升结果。
采用一些小小的技巧,可以使得算法不一定要背景笔 也能得到目标分割
算法前期处理改进可以有两个方面,meanshift 和watershed。
前期处理测试watershed floodfilled 效果都不佳,最后加入Meanshift结合金字塔算法对图像进行平滑,平滑前用floodfilled算法 很难获取比较大的区域,平滑后,如果目标不是很复杂,可以获取整个目标区域。
将用gimp测试图跑的结果放上来:
为了速度快,我将图压缩了,所以会有一点锯齿。
如果没有这个需求 可以跑出很精致的图的。
最新价格比较:
ARM主控专区
S5PV210AA0-LA40 USD:7 含税最新价格:56元人民币 (在产)
S3C44B0X01-ED80 USD:2.86
S3C2410A20-YO80 USD:4.43 ( 停产)
S3C2410A26-YO80 USD:5.06
S3C2416X40-Y640 USD:3.7 (在产)
S3C2416X53-Y640
S3C2443X40-YL80 USD:5.55
S3C2451X40-YY40 USD:4.75
S3C2451X53-YY40
S3C2440A40-YO80 USD:6.5 ( 停产)
S3C4510B01-QE80 USD:2.3
S3C4510D01-QE80
S3C6410X66-YB40 USD:8.15 ( 停产)
S3C6410X53-YB40
S5PC100A80-LA40
以上价格是最新更新的,足可见S5PV210的应用潜力。厦门区域我们使用量最大,有样机、样品、开发板供参考。欢迎联系垂询!
最近做了很多sns开发平台分享的东西,说一下自己的观点
1.新浪微博2.0 最差 无论是demo还是文档还是sdk的维护,各种问题 ,和1.0没法比,怀疑新浪到底还想不想开放了,好歹也是个大公司,居然写出那么恶心的代码
2.腾讯1.0也很差,但是腾讯2.0不错(不得不承认人家的技术实例),只是权限很少,功能也不多,很多东西可能要自己解析json 自己写网络逻辑.其实最恶心的还是权限,现在发个说说的权限都要申请.不要建议我用腾讯微博接入,有人用吗?
3.人人sdk 功能比较全面,架构也很好,可能好像人人是这个三个中最不是很普及的.正应了某个人人职员的话
"人人不是腾讯百度他们那么多的项目,每个人都会真正参与进去的"
这可能也暗示人人的专注一些吧.
看了人人的sdk感觉自己可以学习很多东西,现在整理如下
人人网SDK Demo项目学习 1 全局标题栏
人人的全局标题栏使用BaseActivity实现,其他用到标题栏的都继承他,
其他优点:
方便在BaseActivity中处理一些UI操作,比如显示toast等,
获取手机IMEI等的 需要使用context的方法 就不用各种传递context了.
BaseActivity的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/renren_demo_root" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/main_bg" android:orientation="vertical" > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/renren_demo_titlebar" android:layout_width="fill_parent" android:layout_height="50dip" android:background="@drawable/renren_demo_titlebar_background" android:paddingBottom="10dip" android:paddingLeft="10dip" android:paddingRight="10dip" android:paddingTop="10dip" > <Button android:id="@+id/renren_demo_titlebar_left_button" android:layout_width="60dip" android:layout_height="40dip" android:layout_alignParentLeft="true" android:background="@drawable/renren_demo_titlebar_left_button" android:text="返回" android:textColor="#FFFFFF" android:textSize="14sp" /> <TextView android:id="@+id/renren_demo_titlebar_title_text" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:text="" android:textColor="#FFFFFF" android:textSize="20sp" /> <Button android:id="@+id/renren_demo_titlebar_right_button" android:layout_width="60dip" android:layout_height="40dip" android:layout_alignParentRight="true" android:background="@drawable/renren_demo_titlebar_right_button" android:text="查看Log" android:textColor="#FFFFFF" android:textSize="14sp" /> </RelativeLayout> </LinearLayout>
BaseActivity代码(增加了一个获取设备ID方法)
/** * $id$ */ package com.renren.api.connect.android.demo.activity; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.TelephonyManager; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.renren.api.connect.android.Renren; import com.renren.api.connect.android.demo.R; /** * Base class for request Activity in the demo application * * @author Shaofeng Wang (shaofeng.wang@renren-inc.com) */ public class BaseActivity extends Activity { /** * 根布局对象,用于在将来的子类中添加内容布局 */ protected LinearLayout root; /** * 标题栏左边按钮 */ protected Button titlebarLeftButton; /** * 标题栏中间文字 */ protected TextView titlebarText; /** * 标题栏右边按钮 */ protected Button titlebarRightButton; private ProgressDialog progressDialog; /** * 调用SDK接口的Renren对象 */ protected Renren renren; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置不显示标题栏 requestWindowFeature(Window.FEATURE_NO_TITLE); // 设置布局 setContentView(R.layout.base_layout); // 初始化控件 root = (LinearLayout) findViewById(R.id.renren_demo_root); titlebarLeftButton = (Button) findViewById(R.id.renren_demo_titlebar_left_button); titlebarRightButton = (Button) findViewById(R.id.renren_demo_titlebar_right_button); titlebarText = (TextView) findViewById(R.id.renren_demo_titlebar_title_text); // 注册“查看Log”按钮事件 titlebarRightButton.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(BaseActivity.this, LogActivity.class); BaseActivity.this.startActivity(intent); } }); // 注册“返回”按钮事件(子类若有不同的处理,则需覆盖此事件) titlebarLeftButton.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { finish(); } }); Intent intent = getIntent(); renren = intent.getParcelableExtra(Renren.RENREN_LABEL); if (renren != null) { renren.init(this); } } /** * 解析逗号分割的字符串 * * @return */ protected String[] parseCommaIds(String s) { if (s == null) { return null; } String[] ids = s.split(","); return ids; } /** * 显示等待框 */ protected void showProgress() { showProgress("Please wait", "progressing"); } /** * 显示等待框 * * @param title * @param message */ protected void showProgress(String title, String message) { progressDialog = ProgressDialog.show(this, title, message); } /** * 取消等待框 */ protected void dismissProgress() { if (progressDialog != null) { try { progressDialog.dismiss(); } catch (Exception e) { } } } /** * 显示Toast提示 * * @param message */ protected void showTip(String message) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } @Override protected void onDestroy() { super.onDestroy(); // 不销毁ProgressDialog会出现view not attached to window manager异常 dismissProgress(); } protected String getDeviceId() {//获取设备ID TelephonyManager tm = (TelephonyManager) this .getSystemService(Context.TELEPHONY_SERVICE); return tm.getDeviceId(); } }
测试一下
package com.renren.api.connect.android.demo; import com.renren.api.connect.android.demo.activity.BaseActivity; import android.os.Bundle; import android.view.View; import android.widget.LinearLayout; public class TestActivity extends BaseActivity { @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); LinearLayout mainLayout = (LinearLayout) getLayoutInflater().inflate( R.layout.main, null); root.addView(mainLayout);// 继承了BaseActivity // 想要再次添加布局就要使用这个方法了,如果在使用setContentView()就会把父类定义的标题栏覆盖了 titlebarRightButton.setOnClickListener(new View.OnClickListener() {// 重写BaseActivity的方法,改变他的事件 @Override public void onClick(View v) { showProgress(); } }); showTip("测试" + getDeviceId()); } }