计算矩形数量

我在窗口 绘制了 3 个矩形 矩形 id 分别为 1,2,3
当我删除2 ,在添加一个矩形时 他的id 为2
如果删除3 时 ,在添加一个矩形 他的id为3
删除1时,在添加一个矩形他的id为1
球高手给点思路

回答: 计算矩形数量

  1. 不就是保证 id 连续吗?
    添加时,找到第一个缺失的id

数组处理,计算ng数量

  1. Q

    array(6) {
      [0]=>
      string(62) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020.csv"
      [1]=>
      string(64) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_1.csv"
      [2]=>
      string(64) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_2.csv"
      [3]=>
      string(64) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_3.csv"
      [4]=>
      string(64) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_4.csv"
      [5]=>
      string(65) "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_NG.csv"
    }


    已知数组a的形式,如果把7020开头的文件看作一个文件,求得这样的结果:ts407,bed410-500a1,5306,ng对应数量为1.这要怎么求?
  2. A

    $arr=array(
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_1.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_2.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_3.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_4.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7020_NG.csv",
    "../../dat/DIG/TestFunction/TS407/BED410-500A1/5306/NG/7021_NG.csv",//添加测试
    );
    foreach($arr as $v){
    $tmp=explode('/',$v);
    $lastfile=array_pop($tmp);
    preg_match('/^(\d+)(\.|\_)/',$lastfile,$m);
    $arr_file[]=$m[1];
    }
    $count=count(array_unique($arr_file));
    echo $count;//2

求货物库存台账表计算结存数量和结存金额sql语句

  1. Q
    我现在在做一张货物库存台账表,遇到了难题,请各位大侠帮帮忙指教一下:
    我现在有如下表:
    日期               单据类型     物料     仓库       收入数量  发出数量    rdsflag
    2009-01-01  外购入库   A物料   A仓库          1                 0             1
    2009-02-01  其他入库   A物料   A仓库          3                 0        1
    2009-03-01  销售出库   A物料   A仓库          0                 2       -1
    2009-01-02  外购入库   B物料   B仓库         4                 0              1
    2009-02-02  其他入库   B物料   B仓             2                 0             1
    2009-03-02  销售出库   B物料   B仓             0                 4             -1
    如何写出每种货物当日的结存数量的SQL?
    能得到如下的结果?   
    日期               单据类型     物料      仓库      收入数量  发出数量  结存数量
                                                                                                             10
    2009-01-01  外购入库   A物料    A仓库            1         0        11
    2009-02-01  其他入库   A物料    A仓库            3         0        14
    2009-03-01  销售出库   A物料    A仓库            0         2        12
    2009-01-02  外购入库   B物料    B仓库            4         0        16
    2009-02-02  其他入库   B物料    B仓库            2         0        18    
    2009-03-02  销售出库   B物料    B仓库            0         4        14  


    表结构:
    create table tt
    (
       StockDate       datetime,         //业务日期
       SrcType           varchar(50),    //单据类型
       GoodName    varchar(50),    //货物名称
       Branch            varchar(50),    //仓库
       NUM                Decimal(28,10),  //出入库/数量
      rdsflag              int                          
    )                 




    存储过程
    SET QUOTED_IDENTIFIER ON 
    GO
    SET ANSI_NULLS ON 
    GO
    ALTER procedure cx_getAccount_RD @StockDate datetime, @enddate datetime
    as
    SET NOCOUNT ON
    SET ANSI_WARNINGS OFF
    --库存台帐表
    declare @num decimal( 18, 2) --期初件数
    declare @TotalPrice decimal( 18, 2) --期初金额

    SELECT @num=SUM( rdsFlag * Num1)
    FROM tt
    WHERE StockDate <@StockDate

    SELECT NULL AS 业务日期, '' as 单据类型, '' AS 仓库, 
    '' as 货物名称, 
    0 AS 入库件数,
    0 AS 出库件数,
    ISNULL(@num, 0) AS 结存件数,

    UNION ALL

    SELECT StockDate,SrcType,Branch,GoodsName,
    SIGN(rdsflag + 1) * Num AS 入库件数,
    SIGN(rdsflag - 1) * - 1 * Num1 AS 出库件数,
    这里不知道怎么写 as 结存件数
    FROM tt
    WHERE StockDate >[email protected] AND StockDate <[email protected]
    go

    求大神指教
  2. A
    CREATE procedure cx_getAccount_RD
    @StockDate datetime, @enddate datetime
    AS
    BEGIN
    SET NOCOUNT ON
    SET ANSI_WARNINGS OFF

    ;WITH ttCTE AS(
    SELECT *
    ,ROW_NUMBER()OVER(PARTITION BY GoodName,Branch ORDER BY StockDate)RN
    FROM tt
    WHERE StockDate>[email protected] AND StockDate<[email protected]
    )
    ,CTE AS(
    SELECT
    T1.StockDate--业务日期
    ,T1.SrcType--单据类型
    ,T1.GoodName--货物名称
    ,T1.Branch--仓库
    ,CASE WHEN T1.rdsFlag>0 THEN T1.NUM ELSE 0 END InNUM--收入数量
    ,CASE WHEN T1.rdsFlag<0 THEN T1.NUM ELSE 0 END OutNUM--发出数量
    ,ISNULL(T2.NUM1,0)+T1.NUM*T1.rdsFlag SUMNUM--结存数量
    ,T1.RN
    FROM
    ttCTE T1
    LEFT JOIN(
    SELECT GoodName,Branch
    ,SUM(rdsFlag*NUM)NUM1
    FROM tt
    WHERE StockDate<@StockDate
    GROUP BY GoodName,Branch
    )T2 ON T1.GoodName=T2.GoodName AND T1.Branch=T2.Branch
    WHERE T1.RN=1
    UNION ALL
    SELECT
    T1.StockDate
    ,T1.SrcType
    ,T1.GoodName
    ,T1.Branch
    ,CASE WHEN T1.rdsFlag>0 THEN T1.NUM ELSE 0 END InNUM
    ,CASE WHEN T1.rdsFlag<0 THEN T1.NUM ELSE 0 END OutNUM
    ,T2.SUMNUM+T1.NUM*T1.rdsFlag
    ,T1.RN
    FROM ttCTE T1
    JOIN CTE T2 ON T1.GoodName=T2.GoodName AND T1.Branch=T2.Branch
    AND T1.RN=T2.RN+1
    )
    SELECT * FROM CTE
    ORDER BY GoodName,Branch,RN
    END
    GO
    ----
    EXEC cx_getAccount_RD '2009-01-01','2009-03-02'

一个比较纠结的问题。将一个固定长宽的矩形,随机分割成若干随机大小的矩形

  1. Q
    有木有比较好一点的算法。。。

    我的思路是:
    1:得到总面积,随机得到分割小矩形的个数。
    2:将总面积分给若干个小矩形。
    3:计算小矩形长和等于总长,宽和等于总宽,取其中一种。

    有木有更好的办法,高人指点一下!!!感谢。最好是有java代码。。

    原帖:
  2. A
    试试我这个方法。
    (1)  如果要求分割的矩形数量为1,则返回自身
    (2)  如果要求分割的矩形数量为2,则在四条边(四个顶点除外)上随机取一个点,可以分割两个矩形,完成。
    (3) 如果要求分割的矩形为n,且n > 2,则先递归分出n - 1个小矩形,然后任取一个小矩形,分割出2个小矩形,完成。

能否直接调用 Windows的目录算法来实现数据库的树形计算?

  1. Q
    1.最近我们要开发一款  线上教育平台 。
    2.除了一般教育平台的元素外,此教育平台还有一个比

    较麻烦的地方,就是其数据库结构---可能要用到树形
    算法 或  递归。
    3.此教育平台中没有 明确意义上的 老师 和 学生,每个

    人都可以同时充当 老师 和 学生 两种角色。

    4.当用户作为学生时,只能添加一位 老师。用户作为 老师时,可以添加无数学生。
    PS:即 父节点 下可以有无数 子节点。 每个 子节点  能有一个 父节点。


    5.那么,每个用户 在数据表中,都有两种明确的用户关

    系。分别是
    (1)下线关系,或  下级节点关系:自己的 学生、自己

    学生的学生、自己学生的学生的学生。。。。无限循


     (2)上线关系,或  父节点 关系: 自己的老师、自己

    老师的老师、自己老师的老师的老师。。。一直到最顶层的 根节点(没有老师的 用户)。



    6.系统要可以明确统计出  每个 用户(父节点) 名下的 

    学生数量(包括  学生的学生)

    7.要避开 死循环 的情况。例如  A是B的老师。B是C的老

    师,C是D的老师。那么D便不可以是A的老师。

    8.我们希望 树形机构 的 深度 是无限的。

    但我对oracle不是很熟悉,不知如何设计这种树状的数据库。所以我想了一个解决方案。
    或许有点笨,但好像简化了开发流程。。希望各位给点意见


    9.如果上述用户关系实在设计不出来的话,可以按照以

    下思路设计:
    【1】在一个服务器下构建一个大的根目录.
    【2】每新注册一位用户,便在 根目录下创建一个 新的

    文件夹。(文件夹不能重名)
    【3】每个 文件夹 代表一个用户。
    【4】确保每个文件夹的大小一样或“近乎相等”。
    【5】用户 建立 师生 关系的时候,便将 学生用户 的文

    件夹 剪切粘贴 到  老师用户 的文件夹面。
         举个列子吧:
          服务器的 根目录 为 ROOT \
          那么
         A用户注册的时候,ROOT\下创建一个名为A的文件夹 

    。路径为 ROOT \ A \
         B用户注册的时候,在ROOT\下创建一个名为B的文件

    夹。路径为ROOT \ B \
         C用户注册的时候,在ROOT\下创建一个名为C的文件

    夹。
        如果现在 A用户想 拜 B用户为师,B用户收A用户为学

    生。那么 系统只要将  ROOT\A剪切 粘贴到 ROOT\B里就OK

    了。粘贴后,A文件夹的路径就变为
       ROOT\B\A
         如果B用户又想继续添加C用户为师,C想收B为徒弟

    。那么,只要将 ROOT\B剪切粘贴到ROOT\C就好了。
       剪切后,B的路径为ROOT\C\B.    而A的路径为 

    ROOT\C\B\A...
         如果现在A用户不想要B用户做老师了,想改拜C用户

    为师,那么,只要把 A剪切到 C下就OK了。
    剪切后,A的路径为ROOT\C\A. 
        
     10.那么,当用户要注册,建立 和 变更 师生关系时,只

    要向 服务器发送  新建、 剪切 和 粘贴  指令就OK了。用

    户要查自己在树形结构中的位置时,可以  直接调用 服

    务器的  资源管理器。。 

    11.当然,这样做的话,最大的问题是可能 卡成刘翔。

    报价的时候必须告诉我要用怎样的  服务器配置,方能

    保证有200万以上用户依然能保证使用的流畅性,而不

    至于降低用户体验。



    ----我是分割线--

    不知道上述的思路是否可行??

    还有,怎么从理论上计算  用户数量、反应速度、系统运算能力之间的关系????因为如果我要施行这个方案的话,或许需要一台很厉害的电脑做 服务器。。但我怎么确定要多厉害的主机才足够呢 ?
  2. A
    LZ的这个需求比较有意思,其实单就每个人而言,可视为一个节点,此节点可拥有两类单项箭头,一个为指向其他节点的箭头,下文中称为老师箭头,另一类为指向自己的箭头,下文中称为学生箭头,则这个问题就演化为有向图遍历问题了,实现个DFS就是了

如何分页打印ListView中的数据,请大侠指点一下

  1. Q
    C#  开发WinForm,开发环境为Visual Studio2010

    假设ListView中有N条数据,现在需要打印出来,每页打印20条数据,请给点代码我看看,谢谢!如何分页打印ListView中的数据,请大侠指点一下



    我自作聪明些了一段试了一下,发现不行啊如何分页打印ListView中的数据,请大侠指点一下



     private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
            {
               ………………
                int Pages = Lst.Items.Count / 20;//计算页面数量
                Pages += 1;

                while (count < 20)//每页最多打印20行
                {
                    yPosition = topMargin + (count * printFont.GetHeight(g));
                    g.DrawString(Lst.Items[count].Text, printFont, myBrush, leftMargin, yPosition, new StringFormat());
                    g.DrawString(Lst.Items[count].SubItems[1].Text, printFont, myBrush, (leftMargin + 10), yPosition, new StringFormat());
                    count++;
                }

                if (Pages > 1)
                {
                    e.HasMorePages = true;
                    Pages--;
                }

    }

  2. A
    我只用过Devexpress的XtraReport,可以编码控制生成……也可以简单的绑定生成

这种MOUSE_MOVE事件,如何处理??

  1. Q
    先上图:
    这种MOUSE_MOVE事件,如何处理??


    功能很简单,就是鼠标移动到哪个方框内,方框就变成红色。
    我是这样做的:
    方框的信息都是用list存起来的,包括 RECT 等,绘制的时候,用GDI的Rectangle绘制出来。

    最关键的是鼠标事件,我直接用的控件的 mouse_move 事件,在事件中,把整个矩形list遍历一遍,伪代码如下:

    for(it=list.begin();it!=list.end();it++)
    {
        if( PtInRect(it->rc,Mousept) )
        {
            DrawRedRect();
            break;
        }
    }

    功能是实现了,但是现在有个问题,当矩形数量较多时画面上一共有(2772个矩形),在窗体上晃动鼠标,CPU的使用率太高了,20%左右,这是不能接受的。。。。。

    忽然想起,在BCB中,很多控件有MOUSE_ENTER和MOUSE_LEAVE事件,如果把这些矩形都换成相应的控件呢?如果换成了2772个控件,在晃动鼠标时,CPU占用率几乎是0%,这是怎么实现的呢???
  2. A
    多个组件共用一个事件处理函数,用过Sender来判断是谁触发的事件,这个方法试过没?

「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

  1. Q
    看到有趣的东西,忍不住翻译过来了。

    ----------------

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序


    © 版权所有 野比 2012
    原文地址:点击查看
    作者:Nazmi Altun「土耳其」

    源码下载:点我

    demo下载:点我

    介绍
    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    (图片上的字:方块4,方块J,黑桃2)

    用机器人配上扑克牌识别系统,就可以在二十一点一类的扑克游戏中扮演荷官或是人类玩家的角色。实现这样的程序同样也是学习计算机视觉和模式识别的好途径。
    本文涉及到的AForge.NET框架技术有二值化、边缘检测、仿射变换、BLOB处理和模板匹配算法等。
    需要注意的是,这篇文章和文中介绍的系统是针对英美扑克设计的,可能不适用于其他种类的扑克。然而,本文描述了扑克的检测和识别的基本方法。因此,具体的识别算法需要根据扑克牌型特点而加以变化。
    这里有一个视频演示。
    YouTube
    直接访问      通过代理访问(在代理页面输入http://www.youtube.com/watch?v=dui3ftwsuhM然后访问)

    (话说我传到优酷上了怎么总是「发布中」呢?)

    扑克检测
    我们需要检测图像(指采集到的视频画面,下同——野比注)上的扑克对象,以便能进行下一步的识别。为了完成检测,我们会用一些图像滤镜对视频画面进行处理。
    第一步,将图像去色(即灰度化——野比注)。去色是将彩色图像转换成8bit图像的一种操作。我们需要将彩色图像转换为灰度图像以便对其进行二值化。
    我们把彩色图像转为灰度图像后,对其进行二值化。二值化(阈值化)是将灰度图像转换为黑白图像的过程。本文使用Otsu的方法进行全局阈值化。

    Bitmap temp = source.Clone() as Bitmap; // 复制原始图像
     
     FiltersSequence seq = new FiltersSequence();
     seq.Add(Grayscale.CommonAlgorithms.BT709);  // 添加灰度滤镜
     seq.Add(new OtsuThreshold()); // 添加二值化滤镜
     temp = seq.Apply(source); // 应用滤镜


    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序


    (图片上的字:原始图像、灰度图像、二值(黑白)图像)
    有了二值图像后,就可以用BLOB处理法检测扑克牌了。我们使用AForge.Net的BlobCounter类完成这项任务。该类利用连通区域标记算法统计并提取出图像中的独立对象(即扑克牌——野比注)。
    // 从图像中提取宽度和高度大于150的blob
     BlobCounter extractor = new BlobCounter();
     extractor.FilterBlobs = true;
     extractor.MinWidth = extractor.MinHeight = 150;
     extractor.MaxWidth = extractor.MaxHeight = 350;
     extractor.ProcessImage(temp);


    执行完上述代码后,BlobCounter类会滤掉(去除)宽度和高度不在[150,350]像素之间的斑点(blob,即图块blob,图像中的独立对象。以下将改称图块——野比注)。这有助于我们区分出图像中其他物体(如果有的话)。根据测试环境的不同,我们需要改变滤镜参数。例如,假设地面和相机之间距离增大,则图像中的扑克牌会变小。此时,我们需要相应的改变最小、最大宽度和高度参数。
    现在,我们可以通过调用extractor.GetObjectsInformation()方法得到所有图块的信息(边缘点、矩形区域、中心点、面积、完整度,等等)。然而,我们只需要图块的边缘点来计算矩形区域中心点,并通过调用PointsCloud.FindQuadriteralCorners函数来计算之。
    foreach (Blob blob in extractor.GetObjectsInformation())
     {
      // 获取扑克牌的边缘点
      List< IntPoint > edgePoints = extractor.GetBlobsEdgePoints(blob);
      // 利用边缘点,在原始图像上找到四角
      List< IntPoint > corners =  PointsCloud.FindQuadrilateralCorners(edgePoints);
     }

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    (图片上的字:在图像上绘制边缘点、寻找每张扑克的角)
    找到扑克牌的四角后,我们就可以从原始图像中提取出正常的扑克牌图像了。由上图可以看出,扑克牌可以横放。扑克牌是否横放是非常容易检测的。在扑克牌放下后,因为我们知道,牌的高度是大于宽度的,所以如果提取(转化)图像的宽度大于高度,那么牌必然是横放的。随后,我们用RotateFlip函数旋转扑克牌至正常位置。
    注意,为了正确识别,所有的扑克应当具有相同的尺寸。不过,鉴于相机角度不同,扑克牌的尺寸是会变化的,这样容易导致识别失败。为了防止这样的问题,我们把所有变换后的扑克牌图像都调整为200x300(像素)大小。
    // 用于从原始图像提取扑克牌
     QuadrilateralTransformation quadTransformer = new QuadrilateralTransformation();
     // 用于调整扑克牌大小
     ResizeBilinear resizer = new ResizeBilinear(CardWidth, CardHeight);
     
     foreach (Blob blob in extractor.GetObjectsInformation())
     {
          // 获取扑克牌边缘点
          List<IntPoint> edgePoints = extractor.GetBlobsEdgePoints(blob);
          // 利用边缘点,在原始图像上找到四角
          List<IntPoint> corners =  PointsCloud.FindQuadrilateralCorners(edgePoints);
          Bitmap cardImg = quadTransformer.Apply(source); // 提取扑克牌图像
     
          if (cardImg.Width > cardImg.Height) // 如果扑克牌横放
               cardImg.RotateFlip(RotateFlipType.Rotate90FlipNone); // 旋转之
          cardImg =  resizer.Apply(cardImg); // 归一化(重设大小)扑克牌
            .....
     }

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    (图片上的字:使用QuadriteralTransformation类从原始图像提取出的扑克牌。该类利用每张牌的四角进行变换。)
    到目前为止,我们已经找到了原始图像上每张扑克牌的四角,并从图像中提取出了扑克牌,还调整到统一的尺寸。现在,我们可以开始进行识别了。
     © 版权所有 野比 2012
    识别扑克牌
    有好几种用于识别的技术用于识别扑克牌。本文用到的是基于牌型(如扑克牌上的形状)及模板匹配技术。扑克牌的花色和大小是分开识别的。我们可以这样枚举:
    public enum Rank
     {
         NOT_RECOGNIZED = 0,
         Ace = 1,
         Two,
         Three,
         Four,
         Five,
         Six,
         Seven,
         Eight,
         Nine,
         Ten,
         Jack,
         Queen,
         King
     }
     public enum Suit
     {
         NOT_RECOGNIZED = 0,
         Hearts,
         Diamonds,
         Spades,
         Clubs
     }

    我们还将创建如下的Card类来表示识别到的扑克牌。这个类包括了牌的大小、花色、提取到的扑克牌图像和其在原始图像上的四角点。 
    public class Card
     {
         // 变量
         private Rank rank; // 大小
         private Suit suit; // 花色
         private Bitmap image; // 提取出的图像
         private Point[] corners ;// 四角点
     
         // 属性
         public Point[] Corners
         {
             get { return this.corners; }
         }
         public Rank Rank
         {
             set { this.rank = value; }
         }
         public Suit Suit
         {
             set { this.suit = value; }
         }
         public Bitmap Image
         {
             get { return this.image; }
         }
         // 构造函数
         public Card(Bitmap cardImg, IntPoint[] cornerIntPoints)
         {
             this.image = cardImg;
     
             // 将AForge.IntPoint数组转化为System.Drawing.Point数组
             int total = cornerIntPoints.Length;
             corners = new Point[total];
     
             for(int i = 0 ; i < total ; i++)
             {
                 this.corners[i].X = cornerIntPoints[i].X;
                 this.corners[i].Y = cornerIntPoints[i].Y;
             }
         }
     }

    识别花色
    标准的扑克牌花色有四种:黑桃、梅花、方块和红桃。其中方块和红桃是红色,黑桃和梅花是黑色。再有就是方块的宽度大于红桃,而梅花的宽度大于黑桃。这两个特点可以有助于我们识别花色。
    识别颜色
    首先,我们从识别颜色开始。正确识别出颜色,将帮助我们消除另外两种花色。我们将通过分析扑克牌图像的右上角来识别颜色。(作者强调过,本文基于他所选用的具体的扑克牌型,和印刷、牌面设计有关——野比注)
    public Bitmap GetTopRightPart()
     {
         if (image == null)
             return null;
         Crop crop = new Crop(new Rectangle(image.Width - 37, 10, 30, 60));
     
         return crop.Apply(image);
     }

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    (图片上的字:裁剪 扑克图像右上角、再次裁剪前次图像的底部)
     裁剪了扑克牌右上角后,我们得到一张30x60像素的图像。但是该图像同时包含了花色和大小。因为我们只是分析花色,所以再次裁剪下半部分,得到30x30像素的图像。
    现在,我们可以遍历图像中红色像素和黑色像素的总数。如果一个像素的红色分量比蓝色分量和绿色分量的总和还打,就可以认为该像素是红色。如果红、绿、蓝分量小于50,且红色分量不大于蓝色和绿色分量和,则认为该像素是黑色。
    char color = 'B';
     // 开始,锁像素
     BitmapData imageData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
         ImageLockMode.ReadOnly, bmp.PixelFormat);
     int totalRed = 0;
     int totalBlack = 0;
     
     unsafe
     {
         // 统计红与黑
         try
         {
            UnmanagedImage img = new UnmanagedImage(imageData);
     
            int height = img.Height;
            int width = img.Width;
            int pixelSize = (img.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
            byte* p = (byte*)img.ImageData.ToPointer();
     
            // 逐行
            for (int y = 0; y < height; y++)
            {
                // 逐像素
                for (int x = 0; x < width; x++, p += pixelSize)
                {
                    int r = (int)p[RGB.R]; // 红
                    int g = (int)p[RGB.G]; // 绿
                    int b = (int)p[RGB.B]; // 蓝
     
                    if (r > g + b)  // 红 > 绿 + 蓝
                       totalRed++;  // 认为是红色
     
                    if (r <= g + b && r < 50 && g < 50 && b < 50) // 红绿蓝均小于50
                       totalBlack++; // 认为是黑色
                }
            }
         }
         finally
         {
            bmp.UnlockBits(imageData); // 解锁
         }
     }
     if (totalRed > totalBlack) // 红色占优
         color = 'R'; // 设置颜色为红,否则默认黑色
     return color;

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    注意.NET的Bitmap.GetPixel()函数运行缓慢,所以我们使用了指针来遍历像素。
    区分人物牌和数字牌
    识别了颜色后,我们需要确定扑克牌是否是人物牌。人物牌的牌面为J、Q、K。人物牌和数字牌之间有一个很突出的特点,即数字牌牌面有很多花色符号指示其大小,而人物牌很好辨认,其牌面有人物头像。我们可以简单的设定一个大个的花色形状来分析扑克,而不是对其使用复杂的模板匹配算法。这样,识别数字牌就可以变得更快。
    为了找出一张扑克牌到底是人物牌还是数字牌非常简单。人物牌上面有大的人物图,而数字牌没有。如果我们对牌进行边缘检测和图块(BLOB)处理,找到最大图块,就可以从图块的大小上判断到底是人物牌还是数字牌了。
    private bool IsFaceCard(Bitmap bmp)
     {
        FiltersSequence commonSeq = new FiltersSequence();
        commonSeq.Add(Grayscale.CommonAlgorithms.BT709);
        commonSeq.Add(new BradleyLocalThresholding());
        commonSeq.Add(new DifferenceEdgeDetector());
     
        Bitmap temp = this.commonSeq.Apply(bmp);
        ExtractBiggestBlob extractor = new ExtractBiggestBlob();
        temp = extractor.Apply(temp); // 提取最大图块
     
        if (temp.Width > bmp.Width / 2)  // 如果宽度大于整个牌的一般宽
            return true; // 人物牌
     
        return false;  // 数字牌
     }


    所以我们不断的对扑克牌图像进行灰度变换、局部阈值化和边缘检测。注意我们使用局部阈值化而不是全局阈值化来消除照明不良的问题(即消除光线变换时,相机的自动白平衡造成的屏幕忽明忽暗现象——野比注)。
    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    (图片上的字(上下牌相同):原始扑克图像,灰度化,布拉德利局部阈值化,边缘检测,提取最大图块)
    正如你所看到的,人物牌最大图块几乎和整张扑克牌一样大,很容易区分。
    前面提到过,出于性能上的考虑,我们将使用不同的识别技术对人物牌和数字牌进行识别。对于数字牌,我们直接提取派上最大图块并识别其宽度和颜色。
    private Suit ScanSuit(Bitmap suitBmp, char color)
     {
          Bitmap temp = commonSeq.Apply(suitBmp);
          //Extract biggest blob on card
          ExtractBiggestBlob extractor = new ExtractBiggestBlob();
          temp = extractor.Apply(temp);  //Biggest blob is suit blob so extract it
          Suit suit = Suit.NOT_RECOGNIZED;
     
          //Determine type of suit according to its color and width
          if (color == 'R')
             suit = temp.Width >= 55 ? Suit.Diamonds : Suit.Hearts;
          if (color == 'B')
             suit = temp.Width <= 48 ? Suit.Spades : Suit.Clubs;
     
          return suit;
     }

    「玩一玩」翻译:基于AForge.Net的扑克牌视频识别程序

    上述测试最大误差2像素。一般来说,因为我们把扑克牌尺寸都调整到了200x300像素,所以测试的结果都会是相同的大小。
    人物牌牌面上没有类似数字牌的最大花色图像,只有角上的小花色图。这就是为什么我们会裁剪扑克图像的右上角并对其应用模板匹配算法来识别花色。
    在项目资源文件中有二值化模板图像。(参见项目源代码——野比注)
    AForge.NET还提供了一个叫做ExhaustiveTemplateMatching的类,实现了穷尽模板匹配算法。该类对原始图进行完全扫描,用相应的模板对每个像素进行比较。尽管该算法的性能不佳,但我们只是用于一个小区域(30x60),也不必过于关心性能。

  2. A
    楼主很强大啊!!

【散分】一个视图!

  1. Q
    什么是索引视图?
    多年以来,Microsoft® SQL Server™ 一直支持创建称为视图的虚拟表。通常,这些视图的主要作用是:

    提供一种安全机制,将用户限制到一个或多个基表的某个数据子集中。

    提供一种机制,允许开发人员自定义用户通过逻辑方式查看存储在基表中的数据的方式。
    通过 SQL Server 2000,SQL Server 视图的功能得到了扩展,实现了系统性能方面的收益。可在视图上创建唯一的聚集索引及非聚集索引,来提高最复杂的查询的数据访问性能。在 SQL Server 2000 和 2005 中,具有唯一的聚集索引的视图即为索引视图。本文所讨论的内容适用于 SQL Server 2005,其中有许多内容也适用于 SQL Server 2000。 
    从数据库管理系统 (DBMS) 的角度看来,视图是对数据(一种元数据类型)的一种描述。当创建了一个典型视图时,通过封装一个 SELECT 语句(定义一个结果集来表示为虚拟表)来定义元数据。当在另一个查询的 FROM 子句中引用视图时,将从系统目录检索该元数据,并替代该视图的引用扩展元数据。视图扩展之后,SQL Server 查询优化器会为执行查询编译一个执行计划。查询优化器会搜索针对某个查询的一组可能的执行计划,并根据对执行每个查询计划所需的实际时间的估计,选择所能找到的成本最低的计划。
    对于非索引视图,解析查询所必需的视图部分会在运行时被具体化。任何计算(比如:联接或聚合)都在每个引用视图的查询执行时完成1。在视图上创建了唯一的聚集索引后,该视图的结果集随即被具体化,并保存在数据库的物理存储中,从而在执行时节省了执行这一高成本操作的开销。
    在查询执行中,可通过两种方式使用索引视图。查询可直接引用索引视图,或者更重要的是,如果查询优化器确定该视图可替换成本最低的查询计划中的部分或全部查询,那么就可以选定它。在第二种情况中,使用索引视图替代基础表及其一般索引。不必在查询中引用视图以使查询优化器在查询执行时使用该视图。这使得现有的应用程序可以从新创建的索引视图中受益,而不必进行更改。
    注意 索引视图是 SQL Server 2000 和 2005 各版本的一个功能。在 SQL Server 2000 和 2005 的 Developer 和 Enterprise 版本中,查询处理器可使用索引视图来解析结构上与该视图相匹配的查询,即便不按名称来引用视图。在其他版本中,必须按名称来引用视图,并对视图引用使用 NOEXPAND 提示来查询索引视图的内容。
    通过索引视图改善性能
    运用索引提高查询性能不算是一个新概念;但是,索引视图提供了一些借助标准索引无法取得的性能收益。索引视图可通过以下方式提高查询性能:

    可预先计算聚合并将其保存在索引中,从而在查询执行时,最小化高成本的计算。

    可预先联接各个表并保存最终获得的数据集。

    可保存联接或聚合的组合。
    该图说明了当查询优化器使用索引视图时,通常所能取得的性能改进。所列举的查询在复杂性上有所不同(比如:聚合计算的数量、所用表的数量或谓词的数量)并包含来自真实的生产环境的具有数百万行的表。
    【散分】一个视图!

    在视图上使用非聚集索引
    其次,视图上的非聚集索引可提供更好的查询性能。与表上的非聚集索引类似,视图上的非聚集索引可提供更多选项,供查询优化器在编译过程中选择。例如,如果查询包含聚集索引所未涉及的列,那么优化器可在计划中选择一个或多个辅助索引,避免对索引视图或基表进行费时的完全扫描。
    对架构添加索引会增加数据库的开销,因为索引需要持续的维护。在索引数量和维护开销间寻求适当的平衡点时,应谨慎权衡。
    应用索引视图的优点
    在实施索引视图前,分析数据库工作负荷。运用查询及各种相关工具(比如:SQL Profiler)方面的知识来确定可从索引视图获益的查询。频繁发生聚合和联接的情况最适合使用索引视图。无论是否频繁发生,只要某个查询需要很长的响应时间,同时快速获得响应的开销很高,那么就适合使用索引视图。例如,一些开发人员发现为高级主管们在月末运行的报告,创建预先计算和存储查询的应答的索引视图很有用。
    不是所有的查询都能从索引视图中获益。与一般索引类似,如果未使用索引视图,就无法从中受益。在这种情况下,不仅无法实现性能改善,而且会在磁盘空间、维护和优化方面产生额外的成本。然而,当使用索引视图时,可大大改善(在数量级上)数据访问。这是因为查询优化器使用存储在索引视图(大幅降低了查询执行的成本)中预先计算的结果。
    查询优化器仅考虑对具有高成本的查询使用索引视图。从而避免出现这样的情况:在查询优化成本高于使用索引视图所节约的成本时尝试匹配各种索引视图。在成本少于 1 的查询中很好使用索引视图。
    从实施索引视图中获益的应用程序包括:
    •        决策支持工作负荷
    •        数据集市
    •        数据仓库
    •        联机分析处理 (OLAP) 存储和源
    •        数据挖掘工作负荷
    从查询类型和模式方面来看,获益的应用程序一般包含:
    •        大型表的联接和聚合
    •        查询的重复模式
    •        几组相同或重叠的列上的重复聚合
    •        相同键上相同表的重复联接
    •        以上各项的组合
    相反,执行许多写入操作的联机事务处理 (OLTP) 系统或者频繁更新的数据库应用程序可能无法运用索引视图,因为同时更新视图和底层基表会带来更高的维护成本。
    查询优化器如何使用索引视图
    SQL Server 查询优化器自动决定何时对给定的查询执行使用索引视图。不必在查询中直接引用视图以供优化器在查询执行计划中使用。所以,现有的应用程序可运用索引视图,而不用更改应用程序本身;只是必须创建索引视图。
  2. A
    也许吧

一条查询语句,求思路

  1. Q
    有一张类似如下的表
       id    name     date
       1     名称     20010-3-3
    想在实现如下的报表
        名称   当月数量    年数量    累计数量
    能在一条sql语句里实现嘛?我只能做到按名称分组后计算累计数量
  2. A
    select 名称,sum(case when date between '2013-09-01' and '2013-10-01' then 数量 end) as 9月数量,
    sum(case when date between '2013-01-01' and '2014-01-01' then 数量 end) as 2013年数量,
    sum(数量) 总数量
    from tb
    group by 名称