一个SQL语句的优化

原始SQL如下:

[html]   view plain copy print ?
  1. select * from (  
  2.  select t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,  
  3.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH) slzl,  
  4.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='0') 无评价,  
  5.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='1') 满意,  
  6.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='2') 较满意,  
  7.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='3') 一般,  
  8.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='4') 较不满意,  
  9.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='5') 不满意  
  10.   from xxx t  
  11.   WHERE t.yxbz='Y'   
  12.  )where slzl<>0 ;   

不用看执行计划就知道,表test_v会被扫描多次,所以这个SQL必须改写。如何改写这个SQL呢?请看下面分析:

首先,这个SQL语句是拼出来的,我们可以把复杂的问题简单化,所以我先看这个SQL:

[sql]   view plain copy print ?
  1. select t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,  
  2.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH) slzl  
  3.   from CC_ZXJBXX t  
  4.   WHERE t.yxbz='Y';    

执行计划如下:

[sql]   view plain copy print ?
  1. SQL> select t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,  
  2.   2         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH) slzl  
  3.   3    from CC_ZXJBXX t  
  4.   4    WHERE t.yxbz='Y';  
  5.   
  6. 已选择1956行。  
  7.   
  8. 已用时间:  00: 00: 00.37  
  9.   
  10. 执行计划  
  11. ----------------------------------------------------------  
  12. Plan hash value: 4286326665  
  13.   
  14. --------------------------------------------------------------------------------  
  15. | Id  | Operation          | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  16. --------------------------------------------------------------------------------  
  17. |   0 | SELECT STATEMENT   |           |  1956 |   105K|    11   (0)| 00:00:01 |  
  18. |   1 |  SORT AGGREGATE    |           |     1 |    22 |            |          |  
  19. |*  2 |   TABLE ACCESS FULL| TEST_V    |     4 |    88 |     5   (0)| 00:00:01 |  
  20. |*  3 |  TABLE ACCESS FULL | CC_ZXJBXX |  1956 |   105K|    11   (0)| 00:00:01 |  
  21. --------------------------------------------------------------------------------  
  22.   
  23. Predicate Information (identified by operation id):  
  24. ---------------------------------------------------  
  25.   
  26.    2 - filter("A"."ZCRYZH"=TO_CHAR(:B1))  
  27.    3 - filter("T"."YXBZ"='Y')  

上面的SQL语句会返回1956行,根据执行计划可以看到它进行的是filter操作,讲上面的SQL改写,初步改写如下:

[sql]   view plain copy print ?
  1. SQL> select  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,count(*) from  
  2.   2  CC_ZXJBXX t,test_v a where to_char(t.zxid) = a.ZCRYZH  
  3.   3  and t.yxbz='Y' group by  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm;  
  4.   
  5. 已选择20行。  
  6.   
  7. 已用时间:  00: 00: 00.03  
  8.   
  9. 执行计划  
  10. ----------------------------------------------------------  
  11. Plan hash value: 2833546679  
  12.   
  13. ---------------------------------------------------------------------------------  
  14. | Id  | Operation           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  15. ---------------------------------------------------------------------------------  
  16. |   0 | SELECT STATEMENT    |           | 32157 |  2418K|    22  (28)| 00:00:01 |  
  17. |   1 |  HASH GROUP BY      |           | 32157 |  2418K|    22  (28)| 00:00:01 |  
  18. |*  2 |   HASH JOIN         |           | 32157 |  2418K|    17   (6)| 00:00:01 |  
  19. |   3 |    TABLE ACCESS FULL| TEST_V    |   411 |  9042 |     5   (0)| 00:00:01 |  
  20. |*  4 |    TABLE ACCESS FULL| CC_ZXJBXX |  1956 |   105K|    11   (0)| 00:00:01 |  
  21. ---------------------------------------------------------------------------------  
  22.   
  23. Predicate Information (identified by operation id):  
  24. ---------------------------------------------------  
  25.   
  26.    2 - access("A"."ZCRYZH"=TO_CHAR("T"."ZXID"))  
  27.    4 - filter("T"."YXBZ"='Y')  

 

改写之后,SQL只返回了20条数据,但是原始SQL要返回1956条数据,问题出在哪里呢? 问题在于,第一个SQL是filter,它是过滤,并且是count过滤

而第二个SQL是等值jion,第一个SQL里面的count 不管你过滤成功与否,都会返回数据,过滤失败,count=0 即可,所以对第二个SQL应该用 left join 于是SQL 更改如下:

[sql]   view plain copy print ?
  1. SQL> select  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,count(*) from  
  2.   2  CC_ZXJBXX t,test_v a where to_char(t.zxid) = a.ZCRYZH(+)  
  3.   3  and t.yxbz='Y' group by  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm;  
  4.   
  5. 已选择1956行。  
  6.   
  7. 已用时间:  00: 00: 00.12  
  8.   
  9. 执行计划  
  10. ----------------------------------------------------------  
  11. Plan hash value: 3281235561  
  12.   
  13. ------------------------------------------------------------------------------------  
  14. | Id  | Operation              | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  15. ------------------------------------------------------------------------------------  
  16. |   0 | SELECT STATEMENT       |           | 32157 |  2418K|    22  (28)| 00:00:01 |  
  17. |   1 |  HASH GROUP BY         |           | 32157 |  2418K|    22  (28)| 00:00:01 |  
  18. |*  2 |   HASH JOIN RIGHT OUTER|           | 32157 |  2418K|    17   (6)| 00:00:01 |  
  19. |   3 |    TABLE ACCESS FULL   | TEST_V    |   411 |  9042 |     5   (0)| 00:00:01 |  
  20. |*  4 |    TABLE ACCESS FULL   | CC_ZXJBXX |  1956 |   105K|    11   (0)| 00:00:01 |  
  21. ------------------------------------------------------------------------------------  
  22.   
  23. Predicate Information (identified by operation id):  
  24. ---------------------------------------------------  
  25.   
  26.    2 - access("A"."ZCRYZH"(+)=TO_CHAR("T"."ZXID"))  
  27.    4 - filter("T"."YXBZ"='Y')  

这样改写之后,返回记录条数是对了,但是SQL逻辑有点点改变,第一个SQL是过滤的,count()如果不匹配会返回0,但是第二个SQL是 join的,如果不匹配,会返回1
 



所以SQL需要改写如下:

[sql]   view plain copy print ?
  1. select  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,decode(count(*),1,0,count(*)) from   
  2. CC_ZXJBXX t,test_v a where to_char(t.zxid) = a.ZCRYZH(+)  
  3. and t.yxbz='Y' group by  t.zxid,t.gh,t.xm,t.bm,t.fzjgdm order by 1;  

改写完了一个,后面的就简单了,所以整体的SQL可以改写如下:

[sql]   view plain copy print ?
  1. select t.zxid,  
  2.        t.gh,  
  3.        t.xm,  
  4.        t.bm,  
  5.        t.fzjgdm,  
  6.        decode(count(*), 1, 0, count(*)),  
  7.        SUM(DECODE(A.MYD, '0', 1, 0)) 无评价,  
  8.        SUM(DECODE(A.MYD, '1', 1, 0)) 满意,  
  9.        SUM(DECODE(A.MYD, '2', 1, 0)) 较满意,  
  10.        SUM(DECODE(A.MYD, '3', 1, 0)) 一般,  
  11.        SUM(DECODE(A.MYD, '4', 1, 0)) 较不满意,  
  12.        SUM(DECODE(A.MYD, '5', 1, 0)) 不满意  
  13.   from CC_ZXJBXX t, test_v a  
  14.  where to_char(t.zxid) = a.ZCRYZH(+)  
  15.    and t.yxbz = 'Y'  
  16.  group by t.zxid, t.gh, t.xm, t.bm, t.fzjgdm ;  

上面的SQL等价于

[sql]   view plain copy print ?
  1. select t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,  
  2.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH) slzl,  
  3.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='0') 无评价,  
  4.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='1') 满意,  
  5.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='2') 较满意,  
  6.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='3') 一般,  
  7.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='4') 较不满意,  
  8.        (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='5') 不满意  
  9.   from xxx t  
  10.   WHERE t.yxbz='Y';  

由于原始SQL要去掉 slzl <>0 所以再包装一下

[sql]   view plain copy print ?
  1. select * from   
  2. (select t.zxid,  
  3.        t.gh,  
  4.        t.xm,  
  5.        t.bm,  
  6.        t.fzjgdm,  
  7.        decode(count(*), 1, 0, count(*))slzl,  
  8.        SUM(DECODE(A.MYD, '0', 1, 0)) 无评价,  
  9.        SUM(DECODE(A.MYD, '1', 1, 0)) 满意,  
  10.        SUM(DECODE(A.MYD, '2', 1, 0)) 较满意,  
  11.        SUM(DECODE(A.MYD, '3', 1, 0)) 一般,  
  12.        SUM(DECODE(A.MYD, '4', 1, 0)) 较不满意,  
  13.        SUM(DECODE(A.MYD, '5', 1, 0)) 不满意  
  14.   from CC_ZXJBXX t, test_v a  
  15.  where to_char(t.zxid) = a.ZCRYZH(+)  
  16.    and t.yxbz = 'Y'  
  17.  group by t.zxid, t.gh, t.xm, t.bm, t.fzjgdm  
  18. where slzl<>0;  


原始SQL的执行计划 以及 更改后的执行计划对比:

[sql]   view plain copy print ?
  1. SQL> select * from (  
  2.   2   select t.zxid,t.gh,t.xm,t.bm,t.fzjgdm,  
  3.   3         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH) slzl,  
  4.   4         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='0') 无评价,  
  5.   5         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='1') 满意,  
  6.   6         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='2') 较满意,  
  7.   7         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='3') 一般,  
  8.   8         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='4') 较不满意,  
  9.   9         (select count(a.session_id) from test_v a where to_char(t.zxid) = a.ZCRYZH and a.myd='5') 不满意  
  10.  10    from xxx t  
  11.  11    WHERE t.yxbz='Y'  
  12.  12   ) where slzl<>0;  
  13.   
  14. 已选择20行。  
  15.   
  16. 已用时间:  00: 00: 00.28  
  17.   
  18. 执行计划  
  19. ----------------------------------------------------------  
  20. Plan hash value: 2669170809  
  21.   
  22. ------------------------------------------------------------------------------  
  23. | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     |  
  24. ------------------------------------------------------------------------------  
  25. |   0 | SELECT STATEMENT    |        |  1956 | 76284 |    17   (0)| 00:00:01 |  
  26. |   1 |  SORT AGGREGATE     |        |     1 |     4 |            |          |  
  27. |*  2 |   TABLE ACCESS FULL | TEST_V |    16 |    64 |     5   (0)| 00:00:01 |  
  28. |   3 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  29. |*  4 |   TABLE ACCESS FULL | TEST_V |     9 |    54 |     5   (0)| 00:00:01 |  
  30. |   5 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  31. |*  6 |   TABLE ACCESS FULL | TEST_V |     5 |    30 |     5   (0)| 00:00:01 |  
  32. |   7 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  33. |*  8 |   TABLE ACCESS FULL | TEST_V |     1 |     6 |     5   (0)| 00:00:01 |  
  34. |   9 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  35. |* 10 |   TABLE ACCESS FULL | TEST_V |     2 |    12 |     5   (0)| 00:00:01 |  
  36. |  11 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  37. |* 12 |   TABLE ACCESS FULL | TEST_V |     1 |     6 |     5   (0)| 00:00:01 |  
  38. |  13 |  SORT AGGREGATE     |        |     1 |     6 |            |          |  
  39. |* 14 |   TABLE ACCESS FULL | TEST_V |     1 |     6 |     5   (0)| 00:00:01 |  
  40. |* 15 |  FILTER             |        |       |       |            |          |  
  41. |* 16 |   TABLE ACCESS FULL | XXX    |  1956 | 76284 |    12   (0)| 00:00:01 |  
  42. |  17 |   SORT AGGREGATE    |        |     1 |     4 |            |          |  
  43. |* 18 |    TABLE ACCESS FULL| TEST_V |    16 |    64 |     5   (0)| 00:00:01 |  
  44. ------------------------------------------------------------------------------  
  45.   
  46. Predicate Information (identified by operation id):  
  47. ---------------------------------------------------  
  48.   
  49.    2 - filter("A"."ZCRYZH"=TO_CHAR(:B1))  
  50.    4 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='0')  
  51.    6 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='1')  
  52.    8 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='2')  
  53.   10 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='3')  
  54.   12 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='4')  
  55.   14 - filter("A"."ZCRYZH"=TO_CHAR(:B1) AND "A"."MYD"='5')  
  56.   15 - filter( (SELECT COUNT(*) FROM "TEST_V" "A" WHERE  
  57.               "A"."ZCRYZH"=TO_CHAR(:B1))<>0)  
  58.   16 - filter("T"."YXBZ"='Y')  
  59.   18 - filter("A"."ZCRYZH"=TO_CHAR(:B1))  
  60.   
  61.   
  62. 统计信息  
  63. ----------------------------------------------------------  
  64.           1  recursive calls  
  65.           0  db block gets  
  66.       33261  consistent gets  
  67.           0  physical reads  
  68.           0  redo size  
  69.        2011  bytes sent via SQL*Net to client  
  70.         411  bytes received via SQL*Net from client  
  71.           3  SQL*Net roundtrips to/from client  
  72.           0  sorts (memory)  
  73.           0  sorts (disk)  
  74.          20  rows processed  

原始SQL需要消耗33261个逻辑读,扫描TEST_V表8次,更改之后的SQL

[sql]   view plain copy print ?
  1. SQL> select * from  
  2.   2  (select t.zxid,  
  3.   3         t.gh,  
  4.   4         t.xm,  
  5.   5         t.bm,  
  6.   6         t.fzjgdm,  
  7.   7         decode(count(*), 1, 0, count(*))slzl,  
  8.   8         SUM(DECODE(A.MYD, '0', 1, 0)) 无评价,  
  9.   9         SUM(DECODE(A.MYD, '1', 1, 0)) 满意,  
  10.  10         SUM(DECODE(A.MYD, '2', 1, 0)) 较满意,  
  11.  11         SUM(DECODE(A.MYD, '3', 1, 0)) 一般,  
  12.  12         SUM(DECODE(A.MYD, '4', 1, 0)) 较不满意,  
  13.  13         SUM(DECODE(A.MYD, '5', 1, 0)) 不满意  
  14.  14    from CC_ZXJBXX t, test_v a  
  15.  15   where to_char(t.zxid) = a.ZCRYZH(+)  
  16.  16     and t.yxbz = 'Y'  
  17.  17   group by t.zxid, t.gh, t.xm, t.bm, t.fzjgdm  
  18.  18  ) where slzl<>0;  
  19.   
  20. 已选择20行。  
  21.   
  22. 已用时间:  00: 00: 00.01  
  23.   
  24. 执行计划  
  25. ----------------------------------------------------------  
  26. Plan hash value: 1348291491  
  27.   
  28. -------------------------------------------------------------------------------------  
  29. | Id  | Operation               | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  30. -------------------------------------------------------------------------------------  
  31. |   0 | SELECT STATEMENT        |           |    98 |  4410 |    18  (12)| 00:00:01 |  
  32. |*  1 |  FILTER                 |           |       |       |            |          |  
  33. |   2 |   HASH GROUP BY         |           |    98 |  4410 |    18  (12)| 00:00:01 |  
  34. |*  3 |    HASH JOIN RIGHT OUTER|           |  1956 | 88020 |    17   (6)| 00:00:01 |  
  35. |   4 |     TABLE ACCESS FULL   | TEST_V    |   411 |  2466 |     5   (0)| 00:00:01 |  
  36. |*  5 |     TABLE ACCESS FULL   | CC_ZXJBXX |  1956 | 76284 |    11   (0)| 00:00:01 |  
  37. -------------------------------------------------------------------------------------  
  38.   
  39. Predicate Information (identified by operation id):  
  40. ---------------------------------------------------  
  41.   
  42.    1 - filter(DECODE(COUNT(*),1,0,COUNT(*))<>0)  
  43.    3 - access("A"."ZCRYZH"(+)=TO_CHAR("T"."ZXID"))  
  44.    5 - filter("T"."YXBZ"='Y')  
  45.   
  46.   
  47. 统计信息  
  48. ----------------------------------------------------------  
  49.           0  recursive calls  
  50.           0  db block gets  
  51.          62  consistent gets  
  52.           0  physical reads  
  53.           0  redo size  
  54.        1958  bytes sent via SQL*Net to client  
  55.         411  bytes received via SQL*Net from client  
  56.           3  SQL*Net roundtrips to/from client  
  57.           0  sorts (memory)  
  58.           0  sorts (disk)  
  59.          20  rows processed  

逻辑读降低到62,表TEST_V只扫描1次,其实这个SQL只是一个汇总的SQL,稍微有点开发常识的人都知道,最开始写SQL的那个人绝对是在乱写SQL。SQL的优化到这里还没完,

因为我们已经知道这个SQL的目的其实就是汇总,所以直接抛弃刚才的优化思路,直接重写SQL如下:

[sql]   view plain copy print ?
  1. SQL>  SELECT *  
  2.   2    FROM (SELECT T.ZXID,  
  3.   3         T.GH,  
  4.   4         T.XM,  
  5.   5         T.BM,  
  6.   6         T.FZJGDM,  
  7.   7         SUM(1) SLZL,  
  8.   8         SUM(DECODE(A.MYD, '0', 1, 0)) 无评价,  
  9.   9         SUM(DECODE(A.MYD, '1', 1, 0)) 满意,  
  10.  10         SUM(DECODE(A.MYD, '2', 1, 0)) 较满意,  
  11.  11         SUM(DECODE(A.MYD, '3', 1, 0)) 一般,  
  12.  12         SUM(DECODE(A.MYD, '4', 1, 0)) 较不满意,  
  13.  13         SUM(DECODE(A.MYD, '5', 1, 0)) 不满意  
  14.  14    FROM CC_ZXJBXX T ,test_v A  
  15.  15  where A.ZCRYZH=T.ZXID  
  16.  16  and  T.YXBZ = 'Y'  
  17.  17   GROUP BY T.ZXID, T.GH, T.XM, T.BM, T.FZJGDM) order by 1;  
  18.   
  19. 已选择20行。  
  20.   
  21. 已用时间:  00: 00: 00.01  
  22.   
  23. 执行计划  
  24. ----------------------------------------------------------  
  25. Plan hash value: 1317439664  
  26.   
  27. ---------------------------------------------------------------------------------  
  28. | Id  | Operation           | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  29. ---------------------------------------------------------------------------------  
  30. |   0 | SELECT STATEMENT    |           |   411 | 18495 |    18  (12)| 00:00:01 |  
  31. |   1 |  SORT GROUP BY      |           |   411 | 18495 |    18  (12)| 00:00:01 |  
  32. |*  2 |   HASH JOIN         |           |   411 | 18495 |    17   (6)| 00:00:01 |  
  33. |   3 |    TABLE ACCESS FULL| TEST_V    |   411 |  2466 |     5   (0)| 00:00:01 |  
  34. |*  4 |    TABLE ACCESS FULL| CC_ZXJBXX |  1956 | 76284 |    11   (0)| 00:00:01 |  
  35. ---------------------------------------------------------------------------------  
  36.   
  37. Predicate Information (identified by operation id):  
  38. ---------------------------------------------------  
  39.   
  40.    2 - access("T"."ZXID"=TO_NUMBER("A"."ZCRYZH"))  
  41.    4 - filter("T"."YXBZ"='Y')  
  42.   
  43.   
  44. 统计信息  
  45. ----------------------------------------------------------  
  46.           0  recursive calls  
  47.           0  db block gets  
  48.          62  consistent gets  
  49.           0  physical reads  
  50.           0  redo size  
  51.        1945  bytes sent via SQL*Net to client  
  52.         411  bytes received via SQL*Net from client  
  53.           3  SQL*Net roundtrips to/from client  
  54.           1  sorts (memory)  
  55.           0  sorts (disk)  
  56.          20  rows processed  


有时候开发人员,为了完成任务,他才不管你SQL写得好不好呢,能完成功能就行了,相信各位DBA深有体会。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值