diff --git a/EasyPR.vcxproj b/EasyPR.vcxproj index 01ddedc..8132a1a 100644 --- a/EasyPR.vcxproj +++ b/EasyPR.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -20,12 +20,14 @@ Application true Unicode + v120 Application false true Unicode + v120 @@ -41,6 +43,7 @@ true + G:\opencv\opencv\sources\include\opencv2;$(SourcePath) false @@ -89,6 +92,7 @@ + @@ -112,6 +116,7 @@ + diff --git a/EasyPR.vcxproj.filters b/EasyPR.vcxproj.filters index 3a1f070..f4821d7 100644 --- a/EasyPR.vcxproj.filters +++ b/EasyPR.vcxproj.filters @@ -90,6 +90,9 @@ 源文件 + + 源文件 + @@ -125,5 +128,8 @@ 头文件 + + 头文件 + \ No newline at end of file diff --git a/image/baidu_image/test10.jpg b/image/baidu_image/test10.jpg deleted file mode 100644 index da441aa..0000000 Binary files a/image/baidu_image/test10.jpg and /dev/null differ diff --git a/image/baidu_image/test12.jpg b/image/baidu_image/test12.jpg deleted file mode 100644 index c3ae98f..0000000 Binary files a/image/baidu_image/test12.jpg and /dev/null differ diff --git a/image/baidu_image/test13.jpg b/image/baidu_image/test13.jpg deleted file mode 100644 index fdbc384..0000000 Binary files a/image/baidu_image/test13.jpg and /dev/null differ diff --git a/image/baidu_image/test15.jpg b/image/baidu_image/test15.jpg deleted file mode 100644 index 1fc025c..0000000 Binary files a/image/baidu_image/test15.jpg and /dev/null differ diff --git a/image/baidu_image/test16.jpg b/image/baidu_image/test16.jpg deleted file mode 100644 index de10a1e..0000000 Binary files a/image/baidu_image/test16.jpg and /dev/null differ diff --git a/image/baidu_image/test17.jpg b/image/baidu_image/test17.jpg deleted file mode 100644 index 055f41d..0000000 Binary files a/image/baidu_image/test17.jpg and /dev/null differ diff --git a/image/baidu_image/test18.jpg b/image/baidu_image/test18.jpg deleted file mode 100644 index 27ac301..0000000 Binary files a/image/baidu_image/test18.jpg and /dev/null differ diff --git a/image/baidu_image/test19.jpg b/image/baidu_image/test19.jpg deleted file mode 100644 index 58faf15..0000000 Binary files a/image/baidu_image/test19.jpg and /dev/null differ diff --git a/image/baidu_image/test2.jpg b/image/baidu_image/test2.jpg deleted file mode 100644 index 21b19d7..0000000 Binary files a/image/baidu_image/test2.jpg and /dev/null differ diff --git a/image/baidu_image/test5.jpg b/image/baidu_image/test5.jpg deleted file mode 100644 index 0c77b08..0000000 Binary files a/image/baidu_image/test5.jpg and /dev/null differ diff --git a/image/baidu_image/test6.jpg b/image/baidu_image/test6.jpg deleted file mode 100644 index 8651e33..0000000 Binary files a/image/baidu_image/test6.jpg and /dev/null differ diff --git a/image/baidu_image/test7.jpg b/image/baidu_image/test7.jpg deleted file mode 100644 index bef4f63..0000000 Binary files a/image/baidu_image/test7.jpg and /dev/null differ diff --git a/image/baidu_image/test9.jpg b/image/baidu_image/test9.jpg deleted file mode 100644 index 660242d..0000000 Binary files a/image/baidu_image/test9.jpg and /dev/null differ diff --git a/image/general_test.png b/image/general_test.png deleted file mode 100644 index acf36b1..0000000 Binary files a/image/general_test.png and /dev/null differ diff --git a/image/baidu_image/test14.jpg b/image/general_test/京H99999.jpg similarity index 100% rename from image/baidu_image/test14.jpg rename to image/general_test/京H99999.jpg diff --git a/image/general_test/川A019W2.jpg b/image/general_test/川A019W2.jpg new file mode 100644 index 0000000..134fd5a Binary files /dev/null and b/image/general_test/川A019W2.jpg differ diff --git a/image/general_test/川A09X20.jpg b/image/general_test/川A09X20.jpg new file mode 100644 index 0000000..c2054c4 Binary files /dev/null and b/image/general_test/川A09X20.jpg differ diff --git a/image/general_test/川A82M83.jpg b/image/general_test/川A82M83.jpg new file mode 100644 index 0000000..3aa18f5 Binary files /dev/null and b/image/general_test/川A82M83.jpg differ diff --git a/image/general_test/川AA662F.jpg b/image/general_test/川AA662F.jpg new file mode 100644 index 0000000..452f6cf Binary files /dev/null and b/image/general_test/川AA662F.jpg differ diff --git a/image/general_test/川AEK882.jpg b/image/general_test/川AEK882.jpg new file mode 100644 index 0000000..833fb82 Binary files /dev/null and b/image/general_test/川AEK882.jpg differ diff --git a/image/general_test/津JZ3999.jpg b/image/general_test/津JZ3999.jpg new file mode 100644 index 0000000..ba754ab Binary files /dev/null and b/image/general_test/津JZ3999.jpg differ diff --git a/image/general_test/浙A88888.jpg b/image/general_test/浙A88888.jpg index ff8ceef..81376b9 100644 Binary files a/image/general_test/浙A88888.jpg and b/image/general_test/浙A88888.jpg differ diff --git a/image/baidu_image/test8.jpg b/image/general_test/湘G60009.jpg similarity index 100% rename from image/baidu_image/test8.jpg rename to image/general_test/湘G60009.jpg diff --git a/image/baidu_image/test11.jpg b/image/general_test/赣A88888.jpg similarity index 100% rename from image/baidu_image/test11.jpg rename to image/general_test/赣A88888.jpg diff --git a/image/baidu_image/test1.jpg b/image/general_test/鲁B995EQ.jpg similarity index 100% rename from image/baidu_image/test1.jpg rename to image/general_test/鲁B995EQ.jpg diff --git a/image/baidu_image/test3.jpg b/image/general_test/鲁BQG527.jpg similarity index 100% rename from image/baidu_image/test3.jpg rename to image/general_test/鲁BQG527.jpg diff --git a/image/baidu_image/test4.jpg b/image/general_test/黑A16341.jpg similarity index 100% rename from image/baidu_image/test4.jpg rename to image/general_test/黑A16341.jpg diff --git a/image/native_test.png b/image/native_test.png deleted file mode 100644 index 1604d74..0000000 Binary files a/image/native_test.png and /dev/null differ diff --git a/image/native_test/test.jpg b/image/native_test/test.jpg new file mode 100644 index 0000000..e178731 Binary files /dev/null and b/image/native_test/test.jpg differ diff --git a/opencv248.props b/opencv248.props index 0895f81..fba91fc 100644 --- a/opencv248.props +++ b/opencv248.props @@ -1,19 +1,20 @@ - + - $(OPENCV)\include;$(IncludePath) - $(OPENCV)\x86\vc10\lib;$(LibraryPath) - $(OPENCV)\x64\vc10\lib;$(LibraryPath) + $(OPENCV)\include;$(IncludePath) + $(OPENCV)\x86\vc12\lib;$(LibraryPath) + $(OPENCV)\x64\vc10\lib;$(LibraryPath) + G:\opencv\opencv\sources;$(SourcePath) - - opencv_calib3d248d.lib;opencv_contrib248d.lib;opencv_core248d.lib;opencv_features2d248d.lib;opencv_flann248d.lib;opencv_gpu248d.lib;opencv_highgui248d.lib;opencv_imgproc248d.lib;opencv_legacy248d.lib;opencv_ml248d.lib;opencv_nonfree248d.lib;opencv_objdetect248d.lib;opencv_ocl248d.lib;opencv_photo248d.lib;opencv_stitching248d.lib;opencv_superres248d.lib;opencv_ts248d.lib;opencv_video248d.lib;opencv_videostab248d.lib;%(AdditionalDependencies) - - - opencv_calib3d248.lib;opencv_contrib248.lib;opencv_core248.lib;opencv_features2d248.lib;opencv_flann248.lib;opencv_gpu248.lib;opencv_highgui248.lib;opencv_imgproc248.lib;opencv_legacy248.lib;opencv_ml248.lib;opencv_nonfree248.lib;opencv_objdetect248.lib;opencv_ocl248.lib;opencv_photo248.lib;opencv_stitching248.lib;opencv_superres248.lib;opencv_ts248.lib;opencv_video248.lib;opencv_videostab248.lib;%(AdditionalDependencies) - + + opencv_calib3d248d.lib;opencv_contrib248d.lib;opencv_core248d.lib;opencv_features2d248d.lib;opencv_flann248d.lib;opencv_gpu248d.lib;opencv_highgui248d.lib;opencv_imgproc248d.lib;opencv_legacy248d.lib;opencv_ml248d.lib;opencv_nonfree248d.lib;opencv_objdetect248d.lib;opencv_ocl248d.lib;opencv_photo248d.lib;opencv_stitching248d.lib;opencv_superres248d.lib;opencv_ts248d.lib;opencv_video248d.lib;opencv_videostab248d.lib;%(AdditionalDependencies) + + + opencv_calib3d248.lib;opencv_contrib248.lib;opencv_core248.lib;opencv_features2d248.lib;opencv_flann248.lib;opencv_gpu248.lib;opencv_highgui248.lib;opencv_imgproc248.lib;opencv_legacy248.lib;opencv_ml248.lib;opencv_nonfree248.lib;opencv_objdetect248.lib;opencv_ocl248.lib;opencv_photo248.lib;opencv_stitching248.lib;opencv_superres248.lib;opencv_ts248.lib;opencv_video248.lib;opencv_videostab248.lib;%(AdditionalDependencies) + \ No newline at end of file diff --git a/run_accuracy.txt b/run_accuracy.txt new file mode 100644 index 0000000..4ef0099 --- /dev/null +++ b/run_accuracy.txt @@ -0,0 +1,391 @@ +ͳƲ: +ͼƬ:109, δʶͼƬ:15, ʶ:86.2385% +ƽַ:1.89362, ȫƥ:25, ȫƥ:26.5957% +ͳƲ: +ͼƬ:109, δʶͼƬ:25, ʶ:77.0642% +ƽַ:121.512, ȫƥ:19, ȫƥ:22.619% +ͳƲ: +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:2.06452, ȫƥ:23, ȫƥ:24.7312% +ͳƲ: +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:1.91398, ȫƥ:25, ȫƥ:26.8817% +2015-3-10 11:0:7 +ͳƲ: +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:1.91398, ȫƥ:25, ȫƥ:26.8817% +2015-03-10 11:03:51 +ͳƲ: +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:1.91398, ȫƥ:25, ȫƥ:26.8817% +2015-03-10 11:18:54 +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:1.91398, ȫƥ:25, ȫƥ:26.8817% +2015-03-10 12:01:03 +ͼƬ:109, δʶͼƬ:16, ʶ:85.3211% +ƽַ:1.91398, ȫƥ:25, ȫƥ:26.8817% +2015-03-10 12:09:22 +ͼƬ:19, δʶͼƬ:7, ʶ:63.1579% +ƽַ:7.25, ȫƥ:0, ȫƥ:0% +2015-03-10 12:17:31 +ͼƬ:115, δʶͼƬ:16, ʶ:86.087% +ƽַ:2.0404, ȫƥ:24, ȫƥ:24.2424% +2015-03-10 12:20:00 +ͼƬ:14, δʶͼƬ:11, ʶ:21.4286% +ƽַ:3.33333, ȫƥ:1, ȫƥ:33.3333% +2015-03-10 13:58:13 +ͼƬ:14, δʶͼƬ:11, ʶ:21.4286% +ƽַ:3.33333, ȫƥ:1, ȫƥ:33.3333% +2015-03-10 15:11:51 +ͼƬ:14, δʶͼƬ:12, ʶ:14.2857% +ƽַ:5, ȫƥ:0, ȫƥ:0% +2015-03-10 15:45:38 +ͼƬ:14, δʶͼƬ:7, ʶ:50% +ƽַ:3.57143, ȫƥ:0, ȫƥ:0% +2015-03-10 16:07:59 +ͼƬ:14, δʶͼƬ:7, ʶ:50% +ƽַ:3.57143, ȫƥ:0, ȫƥ:0% +2015-03-10 16:10:41 +ͼƬ:14, δʶͼƬ:7, ʶ:50% +ƽַ:3.57143, ȫƥ:0, ȫƥ:0% +2015-03-10 16:16:29 +ͼƬ:14, δʶͼƬ:8, ʶ:42.8571% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-10 16:18:04 +ͼƬ:14, δʶͼƬ:6, ʶ:57.1429% +ƽַ:3.75, ȫƥ:0, ȫƥ:0% +2015-03-10 16:18:36 +ͼƬ:14, δʶͼƬ:7, ʶ:50% +ƽַ:3.71429, ȫƥ:0, ȫƥ:0% +2015-03-10 16:19:33 +ͼƬ:14, δʶͼƬ:5, ʶ:64.2857% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-10 16:22:18 +ͼƬ:14, δʶͼƬ:6, ʶ:57.1429% +ƽַ:3.125, ȫƥ:0, ȫƥ:0% +2015-03-10 16:26:11 +ͼƬ:14, δʶͼƬ:6, ʶ:57.1429% +ƽַ:3.125, ȫƥ:0, ȫƥ:0% +2015-03-10 16:55:35 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 16:57:49 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 17:03:27 +ͼƬ:3, δʶͼƬ:3, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 17:04:32 +ͼƬ:3, δʶͼƬ:3, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 19:08:02 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 19:11:36 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 19:13:20 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 19:14:09 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:8, ȫƥ:0, ȫƥ:0% +2015-03-10 20:47:44 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 21:49:16 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-10 21:50:58 +ͼƬ:9, δʶͼƬ:4, ʶ:55.5556% +ƽַ:2003.2, ȫƥ:0, ȫƥ:0% +2015-03-10 21:55:48 +ͼƬ:9, δʶͼƬ:4, ʶ:55.5556% +ƽַ:2001.4, ȫƥ:0, ȫƥ:0% +2015-03-10 21:57:32 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-10 21:58:36 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:0, ȫƥ:0, ȫƥ:0% +2015-03-10 22:16:26 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:0, ȫƥ:0, ȫƥ:0% +2015-03-10 22:28:54 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:0, ȫƥ:0, ȫƥ:0% +2015-03-10 22:39:46 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:0, ȫƥ:0, ȫƥ:0% +2015-03-10 22:41:49 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:0, ȫƥ:0, ȫƥ:0% +2015-03-10 22:56:46 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:6, ȫƥ:0, ȫƥ:0% +2015-03-10 23:04:39 +ͼƬ:8, δʶͼƬ:2, ʶ:75% +ƽַ:1668.83, ȫƥ:0, ȫƥ:0% +2015-03-10 23:13:19 +ͼƬ:8, δʶͼƬ:2, ʶ:75% +ƽַ:1668.67, ȫƥ:0, ȫƥ:0% +2015-03-12 12:16:23 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:5, ȫƥ:0, ȫƥ:0% +2015-03-12 12:18:19 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-12 12:22:03 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 12:25:36 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 16:34:14 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 16:56:38 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 16:58:34 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 16:59:06 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 17:06:28 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 17:21:58 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:6, ȫƥ:0, ȫƥ:0% +2015-03-12 17:22:28 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:6, ȫƥ:0, ȫƥ:0% +2015-03-12 17:23:08 +ͼƬ:2, δʶͼƬ:1, ʶ:50% +ƽַ:6, ȫƥ:0, ȫƥ:0% +2015-03-12 17:24:05 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 18:05:15 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 20:00:42 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:4, ȫƥ:0, ȫƥ:0% +2015-03-12 20:12:50 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:4, ȫƥ:0, ȫƥ:0% +2015-03-12 20:14:05 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 20:15:11 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 20:24:03 +ͼƬ:8, δʶͼƬ:2, ʶ:75% +ƽַ:3.33333, ȫƥ:0, ȫƥ:0% +2015-03-12 20:25:57 +ͼƬ:8, δʶͼƬ:2, ʶ:75% +ƽַ:3.33333, ȫƥ:0, ȫƥ:0% +2015-03-12 20:45:48 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 20:51:46 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 20:55:28 +ͼƬ:6, δʶͼƬ:0, ʶ:100% +ƽַ:5.16667, ȫƥ:0, ȫƥ:0% +2015-03-12 21:00:18 +ͼƬ:6, δʶͼƬ:0, ʶ:100% +ƽַ:3.33333, ȫƥ:0, ȫƥ:0% +2015-03-12 21:01:17 +ͼƬ:6, δʶͼƬ:0, ʶ:100% +ƽַ:3.33333, ȫƥ:0, ȫƥ:0% +2015-03-12 21:09:27 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 21:11:35 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 21:27:07 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 21:36:34 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 21:40:04 +ͼƬ:3, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 22:32:03 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 22:32:43 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-12 22:35:54 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 22:47:43 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-12 22:57:03 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 23:01:37 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-12 23:33:36 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 00:01:37 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 00:02:17 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 00:03:02 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 10:58:26 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:03:10 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:04:37 +ͼƬ:1, δʶͼƬ:1, ʶ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:05:04 +ͼƬ:1, δʶͼƬ:0, ʶ:100% +ƽַ:2, ȫƥ:0, ȫƥ:0% +2015-03-13 11:07:01 +ͼƬ:117, δʶͼƬ:8, ʶ:93.1624% +ƽַ:2.26606, ȫƥ:26, ȫƥ:23.8532% +2015-03-13 11:19:02 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:21:03 +ͼƬ:117, δʶͼƬ:10, λ:91.453% +ƽַ:2.28972, ȫƥ:26, ȫƥ:24.2991% +2015-03-13 11:24:21 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:2.2844, ȫƥ:26, ȫƥ:23.8532% +2015-03-13 11:24:42 +ͼƬ:15, δʶͼƬ:6, λ:60% +ƽַ:2.66667, ȫƥ:0, ȫƥ:0% +2015-03-13 11:26:40 +ͼƬ:15, δʶͼƬ:7, λ:53.3333% +ƽַ:2.75, ȫƥ:0, ȫƥ:0% +2015-03-13 11:33:09 +ͼƬ:15, δʶͼƬ:6, λ:60% +ƽַ:2.66667, ȫƥ:0, ȫƥ:0% +2015-03-13 11:37:29 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:49:11 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:49:44 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:50:23 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 11:52:39 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:18:49 +ͼƬ:117, δʶͼƬ:33, λ:71.7949% +ƽַ:2.20238, ȫƥ:18, ȫƥ:21.4286% +2015-03-13 12:22:50 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:2.3945, ȫƥ:25, ȫƥ:22.9358% +2015-03-13 12:26:41 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:29:09 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:29:38 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:30:14 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:31:51 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:32:02 +ͼƬ:1, δʶͼƬ:1, λ:0% +ƽַ:-1.#IND, ȫƥ:0, ȫƥ:-1.#IND% +2015-03-13 12:33:55 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:1.97248, ȫƥ:29, ȫƥ:26.6055% +2015-03-13 13:45:18 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:1.97248, ȫƥ:29, ȫƥ:26.6055% +2015-03-13 15:54:58 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:1.97248, ȫƥ:29, ȫƥ:26.6055% +2015-03-13 16:07:49 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:1.97248, ȫƥ:29, ȫƥ:26.6055% +2015-03-13 16:15:55 +ͼƬ:117, δʶͼƬ:8, λ:93.1624% +ƽַ:1.97248, ȫƥ:29, ȫƥ:26.6055% +2015-03-13 16:18:43 +ͼƬ:3, δʶͼƬ:1, λ:66.6667% +ƽַ:4, ȫƥ:0, ȫƥ:0% +2015-03-13 16:20:17 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 16:28:28 +ͼƬ:2, δʶͼƬ:1, λ:50% +ƽַ:6, ȫƥ:0, ȫƥ:0% +2015-03-13 16:50:45 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 16:51:59 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:2.5, ȫƥ:0, ȫƥ:0% +2015-03-13 16:58:34 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:2.5, ȫƥ:0, ȫƥ:0% +2015-03-13 17:06:02 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 17:08:22 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 17:09:37 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 17:10:01 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 17:10:47 +ͼƬ:2, δʶͼƬ:0, λ:100% +ƽַ:3, ȫƥ:0, ȫƥ:0% +2015-03-13 17:12:59 +ͼƬ:117, δʶͼƬ:7, λ:94.0171% +ƽַ:1.95455, ȫƥ:29, ȫƥ:26.3636% +2015-03-13 17:15:45 +ͼƬ:19, δʶͼƬ:5, λ:73.6842% +ƽַ:2.64286, ȫƥ:0, ȫƥ:0% +2015-03-13 17:18:39 +ͼƬ:9, δʶͼƬ:4, λ:55.5556% +ƽַ:2.4, ȫƥ:0, ȫƥ:0% +2015-03-13 17:21:56 +ͼƬ:120, δʶͼƬ:7, λ:94.1667% +ƽַ:1.97345, ȫƥ:29, ȫƥ:25.6637% +2015-03-13 17:31:28 +ͼƬ:6, δʶͼƬ:4, λ:33.3333% +ƽַ:2, ȫƥ:0, ȫƥ:0% +ʱ:5, ƽִʱ:0.833333 +2015-03-13 17:33:30 +ͼƬ:120, δʶͼƬ:7, λ:94.1667% +ƽַ:1.97345, ȫƥ:29, ȫƥ:25.6637% +ʱ:82, ƽִʱ:0.683333 diff --git a/src/core/chars_segment.cpp b/src/core/chars_segment.cpp index c982be8..e9e83b2 100644 --- a/src/core/chars_segment.cpp +++ b/src/core/chars_segment.cpp @@ -90,44 +90,159 @@ Mat CCharsSegment::histeq(Mat in) //getPlateType //жϳƵͣ1Ϊƣ2Ϊƣ0Ϊδ֪Ĭ //ͨɫռĶжϣ0.3ΪƣΪ -int CCharsSegment::getPlateType(Mat input) +int CCharsSegment::getPlateType(Mat src) { - Mat img; - input.copyTo(img); - img = histeq(img); + + //Mat img; + //input.copyTo(img); + //img = histeq(img); + + //double countBlue = 0; + //double countWhite = 0; + + //int nums = img.rows*img.cols; + //for(int i=0; i < img.rows; i++) + //{ + // for(int j=0; j < img.cols; j++) + // { + // Vec3b intensity = img.at(i,j); + // int blue = int(intensity.val[0]); + // int green = int(intensity.val[1]); + // int red = int(intensity.val[2]); + + // if(blue > m_ColorThreshold && green > 10 && red > 10) + // countBlue++; + + // if(blue > m_ColorThreshold && green > m_ColorThreshold && red > m_ColorThreshold) + // countWhite++; + // } + //} + + //double percentBlue = countBlue/nums; + //double percentWhite = countWhite/nums; + + //if (percentBlue - m_BluePercent > 0 && percentWhite - m_WhitePercent > 0) + // return 1; + //else + // return 2; + + //return 0; + + if (plateColorJudge(src, BLUE) == true) { + return 1; + } + else if (plateColorJudge(src, YELLOW) == true) { + return 2; + } + else { + return 1; + } + +} - double countBlue = 0; - double countWhite = 0; +bool CCharsSegment::plateColorJudge(Mat src, const Color r) +{ + Mat src_hsv; + Mat src_color; + cvtColor(src, src_hsv, CV_BGR2HSV); + + vector hsvSplit; + split(src_hsv, hsvSplit); + equalizeHist(hsvSplit[2], hsvSplit[2]); + merge(hsvSplit, src_hsv); + + //blueHΧ + const int min_blue = 100; + const int max_blue = 140; + + //yellowHΧ + const int min_yellow = 15; + const int max_yellow = 40; + + //ƥģɫ,лԲҪĻɫ + int min_h = 0; + int max_h = 0; + switch (r) { + case BLUE: + min_h = min_blue; + max_h = max_blue; + break; + case YELLOW: + min_h = min_yellow; + max_h = max_yellow; + break; + } - int nums = img.rows*img.cols; - for(int i=0; i < img.rows; i++) + float diff_h = float((max_h - min_h) / 2); + int avg_h = min_h + diff_h; + + int max_sv = 255; + int minref_sv = 64; + + int channels = src_hsv.channels(); + int nRows = src_hsv.rows; + //ͼҪͨӰ죻 + int nCols = src_hsv.cols * channels; + + if (src_hsv.isContinuous())//洢ݣһд { - for(int j=0; j < img.cols; j++) + nCols *= nRows; + nRows = 1; + } + + int i, j; + uchar* p; + for (i = 0; i < nRows; ++i) + { + p = src_hsv.ptr(i); + for (j = 0; j < nCols; j += 3) { - Vec3b intensity = img.at(i,j); - int blue = int(intensity.val[0]); - int green = int(intensity.val[1]); - int red = int(intensity.val[2]); + int H = int(p[j]); //0-180 + int S = int(p[j + 1]); //0-255 + int V = int(p[j + 2]); //0-255 - if(blue > m_ColorThreshold && green > 10 && red > 10) - countBlue++; + bool colorMatched = false; - if(blue > m_ColorThreshold && green > m_ColorThreshold && red > m_ColorThreshold) - countWhite++; - } + if (H > min_h && H < max_h) + { + int Hdiff = 0; + if (H > avg_h) + Hdiff = H - avg_h; + else + Hdiff = avg_h - H; + + float Hdiff_p = float(Hdiff) / diff_h; + int min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); + + if ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv)) + colorMatched = true; + } + + if (colorMatched == true) { + p[j] = 0; p[j + 1] = 0; p[j + 2] = 255; + } + else { + p[j] = 0; p[j + 1] = 0; p[j + 2] = 0; + } + } } - double percentBlue = countBlue/nums; - double percentWhite = countWhite/nums; + vector hsvResult; + split(src_hsv, hsvResult); - if (percentBlue - m_BluePercent > 0 && percentWhite - m_WhitePercent > 0) - return 1; - else - return 2; + Mat src_gray = hsvResult[2]; - return 0; + float percent = float(countNonZero(src_gray)) / float(src_gray.rows * src_gray.cols); + + if (percent > 0.5) + return true; + else + return false; } + + + //clearLiuDing //ȥϷť //ÿԪصĽԾСXΪȫ0Ϳڣ diff --git a/src/core/plate.cpp b/src/core/plate.cpp new file mode 100644 index 0000000..8163cb2 --- /dev/null +++ b/src/core/plate.cpp @@ -0,0 +1,13 @@ +#include "../include/plate.h" + +/*! \namespace easypr +Namespace where all the C++ EasyPR functionality resides +*/ +namespace easypr{ + + CPlate::CPlate() + { + //cout << "CPlate" << endl; + } + +} /*! \namespace easypr*/ \ No newline at end of file diff --git a/src/core/plate_detect.cpp b/src/core/plate_detect.cpp index 2411f25..45ac61a 100644 --- a/src/core/plate_detect.cpp +++ b/src/core/plate_detect.cpp @@ -17,7 +17,7 @@ void CPlateDetect::LoadSVM(string s) m_plateJudge->LoadModel(s.c_str()); } -int CPlateDetect::plateDetect(Mat src, vector& resultVec) +int CPlateDetect::plateDetect(Mat src, vector& resultVec, int index) { //dzƵͼ鼯 vector matVec; @@ -51,4 +51,152 @@ int CPlateDetect::plateDetect(Mat src, vector& resultVec) return 0; } + +int CPlateDetect::plateDetectDeep(Mat src, vector& resultVec, bool showDetectArea, int index) +{ + + vector resultPlates; + + vector color_Plates; + vector sobel_Plates; + vector color_result_Plates; + vector sobel_result_Plates; + + vector all_result_Plates; + + //ɫҵnϣnijƣͲٽSobelˡ + const int color_find_max = 4; + + Mat result; + src.copyTo(result); + + m_plateLocate->plateColorLocate(src, color_Plates, index); + m_plateJudge->plateJudge(color_Plates, color_result_Plates); + + + for (int i = 0; i< color_result_Plates.size(); i++) + { + CPlate plate = color_result_Plates[i]; + + RotatedRect minRect = plate.getPlatePos(); + Point2f rect_points[4]; + minRect.points(rect_points); + for (int j = 0; j < 4; j++) + line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 255), 2, 8); + + all_result_Plates.push_back(plate); + } + + if (color_result_Plates.size() >= color_find_max) + { + //ɫҵnϣnijƣͲٽSobelˡ + } + else + { + m_plateLocate->plateSobelLocate(src, sobel_Plates, index); + m_plateJudge->plateJudge(sobel_Plates, sobel_result_Plates); + + for (int i = 0; i< sobel_result_Plates.size(); i++) + { + CPlate plate = sobel_result_Plates[i]; + + RotatedRect minRect = plate.getPlatePos(); + Point2f rect_points[4]; + minRect.points( rect_points ); + for( int j = 0; j < 4; j++ ) + line(result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 2, 8 ); + + all_result_Plates.push_back(plate); + } + } + + for (int i = 0; i < all_result_Plates.size(); i++) + { + // ѽȡijͼηŵϽ + CPlate plate = all_result_Plates[i]; + + Mat plate_area = plate.getPlateMat(); + + int height = m_plateLocate->HEIGHT; + int width = m_plateLocate->WIDTH; + + assert(height*i + height < result.rows); + + Mat imageRoi = result(Rect(0, 0 + height*i, width, height)); + addWeighted(imageRoi, 0, plate_area, 1, 0, imageRoi); + + resultVec.push_back(plate_area); + } + + if (showDetectArea) + { + namedWindow("EasyPR", CV_WINDOW_AUTOSIZE); + showResult(result); + destroyWindow("EasyPR"); + } + + + if (0) + { + stringstream ss(stringstream::in | stringstream::out); + ss << "image/tmp/" << index << "_" << 9 <<"_result" << ".jpg"; + imwrite(ss.str(), result); + } + + return 0; +} + +int CPlateDetect::showResult(const Mat& result) +{ + const int RESULTWIDTH = 640; //640 930 + const int RESULTHEIGHT = 540; //540 710 + + Mat img_window; + img_window.create(RESULTHEIGHT, RESULTWIDTH, CV_8UC3); + + int nRows = result.rows; + int nCols = result.cols; + + Mat result_resize; + if (nCols <= img_window.cols && nRows <= img_window.rows) { + result_resize = result; + + } else if (nCols > img_window.cols && nRows <= img_window.rows) { + float scale = float(img_window.cols) / float(nCols); + resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA); + + } else if (nCols <= img_window.cols && nRows > img_window.rows) { + float scale = float(img_window.rows) / float(nRows); + resize(result, result_resize, Size(), scale, scale, CV_INTER_AREA); + + } else if (nCols > img_window.cols && nRows > img_window.rows) { + Mat result_middle; + float scale = float(img_window.cols) / float(nCols); + resize(result, result_middle, Size(), scale, scale, CV_INTER_AREA); + + if (result_middle.rows > img_window.rows) { + float scale = float(img_window.rows) / float(result_middle.rows); + resize(result_middle, result_resize, Size(), scale, scale, CV_INTER_AREA); + + } + else { + result_resize = result_middle; + } + } else { + result_resize = result; + } + + Mat imageRoi = img_window(Rect((RESULTWIDTH - result_resize.cols) / 2, (RESULTHEIGHT - result_resize.rows) / 2, + result_resize.cols, result_resize.rows)); + addWeighted(imageRoi, 0, result_resize, 1, 0, imageRoi); + + + imshow("EasyPR", img_window); + waitKey(0); + + return 0; +} + + + } /*! \namespace easypr*/ \ No newline at end of file diff --git a/src/core/plate_judge.cpp b/src/core/plate_judge.cpp index 1d27929..f901608 100644 --- a/src/core/plate_judge.cpp +++ b/src/core/plate_judge.cpp @@ -87,5 +87,24 @@ int CPlateJudge::plateJudge(const vector& inVec, return 0; } +//! ԶƽSVMж +int CPlateJudge::plateJudge(const vector& inVec, + vector& resultVec) +{ + int num = inVec.size(); + for (int j = 0; j < num; j++) + { + CPlate inPlate = inVec[j]; + Mat inMat = inPlate.getPlateMat(); + + int response = -1; + plateJudge(inMat, response); + + if (response == 1) + resultVec.push_back(inPlate); + } + return 0; +} + } /*! \namespace easypr*/ diff --git a/src/core/plate_locate.cpp b/src/core/plate_locate.cpp index 64fbba6..8edea90 100644 --- a/src/core/plate_locate.cpp +++ b/src/core/plate_locate.cpp @@ -5,7 +5,7 @@ */ namespace easypr{ -const float DEFAULT_ERROR = 0.6; +const float DEFAULT_ERROR = 0.6;//0.6 const float DEFAULT_ASPECT = 3.75; CPlateLocate::CPlateLocate() @@ -32,12 +32,12 @@ void CPlateLocate::setLifemode(bool param) if(param == true) { setGaussianBlurSize(5); - setMorphSizeWidth(9); - setMorphSizeHeight(3); - setVerifyError(0.9); - setVerifyAspect(4); + setMorphSizeWidth(17); + setMorphSizeHeight(4); + setVerifyError(0.75); + setVerifyAspect(4.0); setVerifyMin(1); - setVerifyMax(30); + setVerifyMax(200); } else { @@ -58,67 +58,1708 @@ bool CPlateLocate::verifySizes(RotatedRect mr) float error = m_error; //Spain car plate size: 52x11 aspect 4,7272 //China car plate size: 440mm*140mmaspect 3.142857 + + //Real car plate size: 136 * 32, aspect 4 float aspect = m_aspect; + //Set a min and max area. All other patchs are discarded //int min= 1*aspect*1; // minimum area //int max= 2000*aspect*2000; // maximum area - int min= 44*14*m_verifyMin; // minimum area - int max= 44*14*m_verifyMax; // maximum area + int min = 34 * 8 * m_verifyMin; // minimum area + int max = 34 * 8 * m_verifyMax; // maximum area + //Get only patchs that match to a respect ratio. float rmin= aspect-aspect*error; float rmax= aspect+aspect*error; - int area= mr.size.height * mr.size.width; - float r = (float)mr.size.width / (float)mr.size.height; - if(r < 1) - { - r= (float)mr.size.height / (float)mr.size.width; - } + int area= mr.size.height * mr.size.width; + float r = (float)mr.size.width / (float)mr.size.height; + if(r < 1) + r= (float)mr.size.height / (float)mr.size.width; + + if(( area < min || area > max ) || ( r < rmin || r > rmax )) + return false; + else + return true; +} + +//! ʾɵijͼ񣬱жǷɹת +Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int index) +{ + Mat img_crop; + + getRectSubPix(src, rect_size, center, img_crop); + + if(m_debug) + { + stringstream ss(stringstream::in | stringstream::out); + ss << "image/tmp/debug_crop_" << index << ".jpg"; + imwrite(ss.str(), img_crop); + } + + Mat resultResized; + resultResized.create(HEIGHT, WIDTH, TYPE); + + resize(img_crop, resultResized, resultResized.size(), 0, 0, INTER_CUBIC); + + if(m_debug) + { + stringstream ss(stringstream::in | stringstream::out); + ss << "image/tmp/debug_resize_" << index << ".jpg"; + imwrite(ss.str(), resultResized); + } + + return resultResized; +} + + +// !HSVռɫ +int CPlateLocate::colorMatch(const Mat& src, const Color r, Mat& out, vector& outRects, int index) +{ + Mat src_hsv; + + // תHSVռдɫҪʹõHɫɫƥ乤 + cvtColor(src, src_hsv, CV_BGR2HSV); + + vector hsvSplit; + split(src_hsv, hsvSplit); + equalizeHist(hsvSplit[2], hsvSplit[2]); + merge(hsvSplit, src_hsv); + + //blueHΧ + const int min_blue = 100; + const int max_blue = 140; + + //yellowHΧ + const int min_yellow = 15; + const int max_yellow = 40; + + //ƥģɫ,лԲҪĻɫ + int min_h = 0; + int max_h = 0; + switch(r) { + case BLUE : + min_h = min_blue; + max_h = max_blue; + break; + case YELLOW : + min_h = min_yellow; + max_h = max_yellow; + break; + } + + float diff_h = float((max_h - min_h) / 2); + int avg_h = min_h + diff_h; + + int max_sv = 255; + int minref_sv = 64; + + int channels = src_hsv.channels(); + int nRows = src_hsv.rows; + //ͼҪͨӰ죻 + int nCols = src_hsv.cols * channels; + + if (src_hsv.isContinuous())//洢ݣһд + { + nCols *= nRows; + nRows = 1; + } + + int i, j; + uchar* p; + for( i = 0; i < nRows; ++i) + { + p = src_hsv.ptr(i); + for ( j = 0; j < nCols; j+=3) + { + int H = int(p[j]); //0-180 + int S = int(p[j+1]); //0-255 + int V = int(p[j+2]); //0-255 + + bool colorMatched = false; + + if (H > min_h && H < max_h) + { + int Hdiff = 0; + if (H > avg_h) + Hdiff = H - avg_h; + else + Hdiff = avg_h - H; + + float Hdiff_p = float(Hdiff) / diff_h; + int min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); + min_sv = 90; // add + if ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv )) + colorMatched = true; + } + + if (colorMatched == true) { + p[j]=0;p[j+1]=0;p[j+2]=255; + } + else { + p[j]=0;p[j+1]=0;p[j+2]=0; + } + } + } + + // ȡɫƥĶֵҶͼ + Mat src_grey; + vector hsvSplit_done; + split(src_hsv, hsvSplit_done); + src_grey = hsvSplit_done[2]; + + /*if (1){ + imshow("src_grey", src_grey); + waitKey(0); + }*/ + + Mat src_threshold; + threshold(src_grey, src_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(10, 2) ); + morphologyEx(src_threshold, src_threshold, MORPH_CLOSE, element); + + /*if (1){ + imshow("color", src_threshold); + waitKey(0); + }*/ + + src_threshold.copyTo(out); + + // + vector< vector< Point> > contours; + + // ע⣬findContoursısrc_threshold + // Ҫsrc_threshold֮ǰʹcopyTo + findContours(src_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + vector>::iterator itc = contours.begin(); + while (itc != contours.end()) + { + RotatedRect mr = minAreaRect(Mat(*itc)); + + // ҪдСߴж + if( !verifySizes(mr)) + itc = contours.erase(itc); + else { + ++itc; + outRects.push_back(mr); + } + } + + return 0; +} + +bool CPlateLocate::sobelJudge(Mat roi) +{ + //Mat roi_blur; + //GaussianBlur(roi, roi_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), + // 0, 0, BORDER_DEFAULT ); + Mat grad; + + int scale = SOBEL_SCALE; + int delta = SOBEL_DELTA; + int ddepth = SOBEL_DDEPTH; + + Mat roi_grey; + cvtColor(roi, roi_grey, CV_RGB2GRAY); + + Mat grad_x, grad_y; + Mat abs_grad_x, abs_grad_y; + + Sobel(roi_grey, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_x, abs_grad_x); + + Sobel(roi_grey, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_y, abs_grad_y); + + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad); + + Mat roi_threshold; + threshold(grad, roi_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight) ); + morphologyEx(roi_threshold, roi_threshold, MORPH_CLOSE, element); + + float channels = roi_threshold.channels(); + float nRows = roi_threshold.rows; + float nCols = roi_threshold.cols; + + float percent = float(countNonZero(roi_threshold)) / float(nRows * nCols); + //cout << "precent:" << percent << endl; + + if (percent >= 0.5) + return true; + else + return false; + +} + + +bool CPlateLocate::charJudge(Mat roi) +{ + int plateType = getPlateType(roi); + Mat roi_gray; + cvtColor(roi, roi_gray, CV_RGB2GRAY); + + //Threshold input image + Mat img_threshold; + if (1 == plateType) + threshold(roi_gray, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + else + threshold(roi_gray, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV); + + //ȥϷԼ·ĺߵȸ + clearLiuDing(img_threshold); + + imshow("charJudge", img_threshold); + waitKey(0); + + vector< vector< Point> > contours; + findContours(img_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // retrieve the external contours + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + //Start to iterate to each contour founded + vector >::iterator itc = contours.begin(); + + vector vecRect; + + while (itc != contours.end()) + { + Rect mr = boundingRect(Mat(*itc)); + Mat auxRoi(img_threshold, mr); + + if (verifyCharSizes(auxRoi)) + vecRect.push_back(mr); + + ++itc; + } + + if (vecRect.size() <= 4) + return false; + + return true; + + + //Mat src_blur; + //GaussianBlur(roi, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), 0, 0, BORDER_DEFAULT); + + //Mat src_grey; + //cvtColor(src_blur, src_grey, CV_RGB2GRAY); + + //Mat src_threshold; + //double otsu_thresh_val = threshold(src_grey, src_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + //Mat src_edge; + //double high_thresh_val = otsu_thresh_val, lower_thresh_val = otsu_thresh_val * 0.5; + //Canny(src_grey, src_edge, lower_thresh_val, high_thresh_val, 3, true); + + //namedWindow("canny", CV_WINDOW_AUTOSIZE); + //imshow("canny", src_edge); + //waitKey(0); + + return true; +} + +//! ַߴ֤ +bool CPlateLocate::verifyCharSizes(Mat r) +{ + //Char sizes 45x90 + float aspect = 45.0f / 90.0f; + float charAspect = (float)r.cols / (float)r.rows; + float error = 0.7; + float minHeight = 10; + float maxHeight = 35; + //We have a different aspect ratio for number 1, and it can be ~0.2 + float minAspect = 0.05; + float maxAspect = aspect + aspect*error; + //area of pixels + float area = countNonZero(r); + //bb area + float bbArea = r.cols*r.rows; + //% of pixel in area + float percPixels = area / bbArea; + + if (percPixels <= 1 && charAspect > minAspect && charAspect < maxAspect && r.rows >= minHeight && r.rows < maxHeight) + return true; + else + return false; +} + + +//getPlateType +//жϳƵͣ1Ϊƣ2Ϊƣ0Ϊδ֪Ĭ +//ͨɫռĶжϣ0.3ΪƣΪ +int CPlateLocate::getPlateType(Mat src) +{ + if (plateColorJudge(src, BLUE) == true) { + return 1; + } + else if (plateColorJudge(src, YELLOW) == true) { + return 2; + } + else { + return 1; + } + +} + +bool CPlateLocate::plateColorJudge(Mat src, const Color r) +{ + Mat src_hsv; + Mat src_color; + cvtColor(src, src_hsv, CV_BGR2HSV); + + vector hsvSplit; + split(src_hsv, hsvSplit); + equalizeHist(hsvSplit[2], hsvSplit[2]); + merge(hsvSplit, src_hsv); + + //blueHΧ + const int min_blue = 100; + const int max_blue = 140; + + //yellowHΧ + const int min_yellow = 15; + const int max_yellow = 40; + + //ƥģɫ,лԲҪĻɫ + int min_h = 0; + int max_h = 0; + switch (r) { + case BLUE: + min_h = min_blue; + max_h = max_blue; + break; + case YELLOW: + min_h = min_yellow; + max_h = max_yellow; + break; + } + + float diff_h = float((max_h - min_h) / 2); + int avg_h = min_h + diff_h; + + int max_sv = 255; + int minref_sv = 64; + + int channels = src_hsv.channels(); + int nRows = src_hsv.rows; + //ͼҪͨӰ죻 + int nCols = src_hsv.cols * channels; + + if (src_hsv.isContinuous())//洢ݣһд + { + nCols *= nRows; + nRows = 1; + } + + int i, j; + uchar* p; + for (i = 0; i < nRows; ++i) + { + p = src_hsv.ptr(i); + for (j = 0; j < nCols; j += 3) + { + int H = int(p[j]); //0-180 + int S = int(p[j + 1]); //0-255 + int V = int(p[j + 2]); //0-255 + + bool colorMatched = false; + + if (H > min_h && H < max_h) + { + int Hdiff = 0; + if (H > avg_h) + Hdiff = H - avg_h; + else + Hdiff = avg_h - H; + + float Hdiff_p = float(Hdiff) / diff_h; + int min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p); + + if ((S > min_sv && S < max_sv) && (V > min_sv && V < max_sv)) + colorMatched = true; + } + + if (colorMatched == true) { + p[j] = 0; p[j + 1] = 0; p[j + 2] = 255; + } + else { + p[j] = 0; p[j + 1] = 0; p[j + 2] = 0; + } + } + } + + vector hsvResult; + split(src_hsv, hsvResult); + + Mat src_gray = hsvResult[2]; + + float percent = float(countNonZero(src_gray)) / float(src_gray.rows * src_gray.cols); + + if (percent > 0.5) + return true; + else + return false; +} + + +//clearLiuDing +//ȥϷť +//ÿԪصĽԾСXΪȫ0Ϳڣ +//XƼֵΪɸʵʵ +Mat CPlateLocate::clearLiuDing(Mat img) +{ + const int x = 5; + Mat jump = Mat::zeros(1, img.rows, CV_32F); + for (int i = 0; i < img.rows; i++) + { + int jumpCount = 0; + for (int j = 0; j < img.cols - 1; j++) + { + if (img.at(i, j) != img.at(i, j + 1)) + jumpCount++; + } + jump.at(i) = jumpCount; + } + for (int i = 0; i < img.rows; i++) + { + if (jump.at(i) <= x) + { + for (int j = 0; j < img.cols; j++) + { + img.at(i, j) = 0; + } + } + } + return img; +} + + +int CPlateLocate::sobelFind(const Mat& src, vector& outRects) +{ + /*Mat src_blur; + GaussianBlur(src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), + 0, 0, BORDER_DEFAULT ); + + Mat grad; + + int scale = SOBEL_SCALE; + int delta = SOBEL_DELTA; + int ddepth = SOBEL_DDEPTH; + + Mat src_gray; + cvtColor(src_blur, src_gray, CV_RGB2GRAY); + + Mat grad_x, grad_y; + Mat abs_grad_x, abs_grad_y; + + Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_x, abs_grad_x); + + Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_y, abs_grad_y); + + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad); + + Mat src_threshold; + double otsu_thresh_val = threshold(grad, src_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight) ); + morphologyEx(src_threshold, src_threshold, MORPH_CLOSE, element);*/ + + //Mat src_threshold; + //sobelOper(src, src_threshold, m_GaussianBlurSize, m_MorphSizeWidth, m_MorphSizeHeight); + + //if (1){ + // imshow("sobel", src_threshold); + // waitKey(0); + //} + + //vector< vector< Point> > contours; + //findContours(src_threshold, + // contours, // a vector of contours + // CV_RETR_EXTERNAL, // ȡⲿ + // CV_CHAIN_APPROX_NONE); // all pixels of each contours + + //vector>::iterator itc = contours.begin(); + // + //while (itc != contours.end()) + //{ + // RotatedRect mr = minAreaRect(Mat(*itc)); + // outRects.push_back(mr); + // ++itc; + //} + + return 0; +} + +//! Sobelһ +//! ƴС״ȡBoundRectһ +int CPlateLocate::sobelFrtSearch(const Mat& src, vector>& outRects) +{ + Mat src_threshold; + sobelOper(src, src_threshold, m_GaussianBlurSize, m_MorphSizeWidth, m_MorphSizeHeight); + + if (0){ + imshow("sobelFrtSearch", src_threshold); + waitKey(0); + } + + vector< vector< Point> > contours; + findContours(src_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + vector>::iterator itc = contours.begin(); + + vector first_rects; + /*while (itc != contours.end()) + { + RotatedRect mr = minAreaRect(Mat(*itc)); + first_rects.push_back(mr); + ++itc; + }*/ + + while (itc != contours.end()) + { + RotatedRect mr = minAreaRect(Mat(*itc)); + + // ҪдСߴж + if (!verifySizes(mr)) + itc = contours.erase(itc); + else { + ++itc; + first_rects.push_back(mr); + } + } + + for (int i = 0; i < first_rects.size(); i++) + { + RotatedRect roi_rect = first_rects[i]; + + Rect_ safeBoundRect; + if ( !calcSafeRect(roi_rect, src, safeBoundRect) ) + continue; + + outRects.push_back(safeBoundRect); + } + return 0; +} + + +//! Sobelڶ +//! ԴС״ƣɲο +int CPlateLocate::sobelSecSearch(const Mat& bound, Point2f refpoint, vector& outRects) +{ + Mat bound_threshold; + + //! ڶβһξϸ + sobelOper(bound, bound_threshold, 3, 10, 3); + + if (0){ + imshow("sobelSecSearch", bound_threshold); + waitKey(0); + } + + vector< vector< Point> > contours; + findContours(bound_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + vector>::iterator itc = contours.begin(); + + vector second_rects; + while (itc != contours.end()) + { + RotatedRect mr = minAreaRect(Mat(*itc)); + second_rects.push_back(mr); + ++itc; + } + + for (int i = 0; i < second_rects.size(); i++) + { + RotatedRect roi = second_rects[i]; + if (verifySizes(roi)) + { + Point2f refcenter = roi.center + refpoint; + Size2f size = roi.size; + double angle = roi.angle; + + RotatedRect refroi(refcenter, size, angle); + outRects.push_back(refroi); + } + } + + return 0; +} + + +int CPlateLocate::sobelFindAgn(const Mat& roi, vector& outRects, vector& resultVec) +{ + Mat roi_blur; + GaussianBlur(roi, roi_blur, Size(3, 3), + 0, 0, BORDER_DEFAULT); + + Mat roi_gray; + cvtColor(roi_blur, roi_gray, CV_RGB2GRAY); + + Mat grad; + + int scale = SOBEL_SCALE; + int delta = SOBEL_DELTA; + int ddepth = SOBEL_DDEPTH; + + Mat grad_x, grad_y; + Mat abs_grad_x, abs_grad_y; + + Sobel(roi_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_x, abs_grad_x); + + Sobel(roi_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_y, abs_grad_y); + + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad); + + Mat roi_threshold; + double otsu_thresh_val = threshold(grad, roi_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(10, 3)); + morphologyEx(roi_threshold, roi_threshold, MORPH_CLOSE, element); + + //if (1){ + // imshow("sobelFindAgn", roi_threshold); + // waitKey(0); + //} + + vector< vector< Point> > contours; + findContours(roi_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + vector >::iterator itc = contours.begin(); + Mat result; + roi.copyTo(result); + + while (itc != contours.end()) + { + RotatedRect minRect = minAreaRect(Mat(*itc)); + if (verifySizes(minRect)) + { + float r = (float)minRect.size.width / (float)minRect.size.height; + float angle = minRect.angle; + Size rect_size = minRect.size; + if (r < 1) + { + angle = 90 + angle; + swap(rect_size.width, rect_size.height); + } + //ץȡķתm_angleǶȣdzƣ + if (angle - m_angle < 0 && angle + m_angle > 0) + { + //if (1) + //{ + // Point2f rect_points[4]; + // minRect.points(rect_points); + // for (int j = 0; j < 4; j++) + // line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 255), 1, 8); + //} + + Rect_ boudRect = minRect.boundingRect(); + + // boudRectϵxyпС0 + float tl_x = boudRect.x > 0 ? boudRect.x : 0; + float tl_y = boudRect.y > 0 ? boudRect.y : 0; + // boudRectϵxyпܴsrcķΧ + float br_x = boudRect.x + boudRect.width < roi.cols ? + boudRect.x + boudRect.width - 1 : roi.cols - 1; + float br_y = boudRect.y + boudRect.height < roi.rows ? + boudRect.y + boudRect.height - 1 : roi.rows - 1; + + float roi_width = br_x - tl_x; + float roi_height = br_y - tl_y; + + if (roi_width <= 0 || roi_height <= 0) + continue; + + // ½һmatȷַԽ磬Էmatλroiʱ쳣 + Rect_ roiRect = Rect_(tl_x, tl_y, roi_width, roi_height); + + Mat roi_mat = roi(roiRect); + Mat img_crop; + + if (0.0 == angle || 90.0 == angle || -90.0 == angle || -0.0 == angle) + { + // ǶȵЩֵҪתֱӾ + // תüеԲֵģ + img_crop = roi_mat; + } + else if (angle - 5 < 0 && angle + 5 > 0) + { + // ǶС5ȣ򲻱תֱʾ + // תüеԲֵģ + img_crop = roi_mat; + } + else + { + // Ƕ5ȵ45֮䣬Ҫת + + //vector rects_tmp; + //deskewP(src_mat, BLUE, rects_tmp); + + Mat rotmat = getRotationMatrix2D(minRect.center, angle, 1); + Mat img_rotated; + + warpAffine(roi_mat, img_rotated, rotmat, roi_mat.size(), CV_INTER_CUBIC); + + Mat middle_crop; + getRectSubPix(img_rotated, rect_size, minRect.center, middle_crop); + + //imshow("middle_crop", middle_crop); + //waitKey(0); + + Mat out; + //deskewP(middle_crop, out, angle); + + img_crop = out; + } + + Mat plate_img; + plate_img.create(HEIGHT, WIDTH, TYPE); + if (img_crop.cols >= WIDTH || img_crop.rows >= HEIGHT) + resize(img_crop, plate_img, plate_img.size(), 0, 0, INTER_AREA); + else + resize(img_crop, plate_img, plate_img.size(), 0, 0, INTER_CUBIC); + + resultVec.push_back(plate_img); + outRects.push_back(minRect); + } + } + itc++; + } + + return 0; +} + + +//! Sobel +//! ɫͼֵͼ +int CPlateLocate::sobelOper(const Mat& in, Mat& out, int blurSize, int morphW, int morphH) +{ + Mat mat_blur; + GaussianBlur(in, mat_blur, Size(blurSize, blurSize), 0, 0, BORDER_DEFAULT); + + Mat mat_gray; + if (mat_blur.channels() == 3) + cvtColor(mat_blur, mat_gray, CV_RGB2GRAY); + else + mat_gray = mat_blur; + + //equalizeHist(mat_gray, mat_gray); + + int scale = SOBEL_SCALE; + int delta = SOBEL_DELTA; + int ddepth = SOBEL_DDEPTH; + + Mat grad_x, grad_y; + Mat abs_grad_x, abs_grad_y; + + Sobel(mat_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_x, abs_grad_x); + + Sobel(mat_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_y, abs_grad_y); + + Mat grad; + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad); + + Mat mat_threshold; + double otsu_thresh_val = threshold(grad, mat_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(morphW, morphH)); + morphologyEx(mat_threshold, mat_threshold, MORPH_CLOSE, element); + + out = mat_threshold; + + return 0; +} + + +//! Ťб +int CPlateLocate::deskew(const Mat& src, const Mat& src_b, vector& inRects, vector& outPlates) +{ + + for (int i = 0; i < inRects.size(); i++) + { + RotatedRect roi_rect = inRects[i]; + + float r = (float)roi_rect.size.width / (float)roi_rect.size.height; + float roi_angle = roi_rect.angle; + + Size roi_rect_size = roi_rect.size; + if (r < 1) { + roi_angle = 90 + roi_angle; + swap(roi_rect_size.width, roi_rect_size.height); + } + + if (roi_angle - m_angle < 0 && roi_angle + m_angle > 0) + { + Rect_ safeBoundRect; + bool isFormRect = calcSafeRect(roi_rect, src, safeBoundRect); + if (!isFormRect) + continue; + + Mat bound_mat = src(safeBoundRect); + Mat bound_mat_b = src_b(safeBoundRect); + + Point2f roi_ref_center = roi_rect.center - safeBoundRect.tl(); + + Mat deskew_mat; + if ((roi_angle - 5 < 0 && roi_angle + 5 > 0) || 90.0 == roi_angle || -90.0 == roi_angle) + { + deskew_mat = bound_mat; + } + else + { + // Ƕ560֮ģҪת rotation + Mat rotated_mat; + Mat rotated_mat_b; + + if (!rotation(bound_mat, rotated_mat, roi_rect_size, roi_ref_center, roi_angle)) + continue; + + if (!rotation(bound_mat_b, rotated_mat_b, roi_rect_size, roi_ref_center, roi_angle)) + continue; + + // ͼƬƫбҪӽת affine + double roi_slope = 0; + + if (isdeflection(rotated_mat_b, roi_angle, roi_slope)) + { + //cout << "roi_angle:" << roi_angle << endl; + //cout << "roi_slope:" << roi_slope << endl; + affine(rotated_mat, deskew_mat, roi_slope); + } + else + deskew_mat = rotated_mat; + } + + Mat plate_mat; + plate_mat.create(HEIGHT, WIDTH, TYPE); + + if (deskew_mat.cols >= WIDTH || deskew_mat.rows >= HEIGHT) + resize(deskew_mat, plate_mat, plate_mat.size(), 0, 0, INTER_AREA); + else + resize(deskew_mat, plate_mat, plate_mat.size(), 0, 0, INTER_CUBIC); + + /*imshow("plate_mat", plate_mat); + waitKey(0);*/ + + CPlate plate; + plate.setPlatePos(roi_rect); + plate.setPlateMat(plate_mat); + outPlates.push_back(plate); + + } + } + return 0; +} + +//! ת +bool CPlateLocate::rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center, const double angle) +{ + Mat in_large; + in_large.create(in.rows*1.5, in.cols*1.5, in.type()); + + int x = in_large.cols / 2 - center.x > 0 ? in_large.cols / 2 - center.x : 0; + int y = in_large.rows / 2 - center.y > 0 ? in_large.rows / 2 - center.y : 0; + + int width = x + in.cols < in_large.cols ? in.cols : in_large.cols - x; + int height = y + in.rows < in_large.rows ? in.rows : in_large.rows - y; + + /*assert(width == in.cols); + assert(height == in.rows);*/ + + if (width != in.cols || height != in.rows) + return false; + + Mat imageRoi = in_large(Rect(x, y, width, height)); + addWeighted(imageRoi, 0, in, 1, 0, imageRoi); + + Point2f center_diff(in.cols/2, in.rows/2); + Point2f new_center(in_large.cols / 2, in_large.rows / 2); + + Mat rot_mat = getRotationMatrix2D(new_center, angle, 1); + + /*imshow("in_copy", in_large); + waitKey(0);*/ + + Mat mat_rotated; + warpAffine(in_large, mat_rotated, rot_mat, Size(in_large.cols, in_large.rows), CV_INTER_CUBIC); + + /*imshow("mat_rotated", mat_rotated); + waitKey(0);*/ + + Mat img_crop; + getRectSubPix(mat_rotated, Size(rect_size.width, rect_size.height), new_center, img_crop); + + out = img_crop; + + /*imshow("img_crop", img_crop); + waitKey(0);*/ + + return true; + + +} + + +//! Ƿƫб +//! ֵͼжϽ +bool CPlateLocate::isdeflection(const Mat& in, const double angle, double& slope) +{ + int nRows = in.rows; + int nCols = in.cols; + + assert(in.channels() == 1); + + int comp_index[3]; + int len[3]; + + comp_index[0] = nRows / 4; + comp_index[1] = nRows / 4 * 2; + comp_index[2] = nRows / 4 * 3; + + const uchar* p; + + for (int i = 0; i < 3; i++) + { + int index = comp_index[i]; + p = in.ptr(index); + + int j = 0; + int value = 0; + while (0 == value && j < nCols) + value = int(p[j++]); + + len[i] = j; + } + + //cout << "len[0]:" << len[0] << endl; + //cout << "len[1]:" << len[1] << endl; + //cout << "len[2]:" << len[2] << endl; + + double maxlen = max(len[2], len[0]); + double minlen = min(len[2], len[0]); + double difflen = abs(len[2] - len[0]); + //cout << "nCols:" << nCols << endl; + + double PI = 3.14159265; + double g = tan(angle * PI / 180.0); + + if (maxlen - len[1] > nCols/32 || len[1] - minlen > nCols/32 ) { + // бΪײ£֮ + double slope_can_1 = double(len[2] - len[0]) / double(comp_index[1]); + double slope_can_2 = double(len[1] - len[0]) / double(comp_index[0]); + double slope_can_3 = double(len[2] - len[1]) / double(comp_index[0]); + + /*cout << "slope_can_1:" << slope_can_1 << endl; + cout << "slope_can_2:" << slope_can_2 << endl; + cout << "slope_can_3:" << slope_can_3 << endl;*/ + + slope = abs(slope_can_1 - g) <= abs(slope_can_2 - g) ? slope_can_1 : slope_can_2; + + /*slope = max( double(len[2] - len[0]) / double(comp_index[1]), + double(len[1] - len[0]) / double(comp_index[0]));*/ + + //cout << "slope:" << slope << endl; + return true; + } + else { + slope = 0; + } + + return false; +} + + +//! Ť +void CPlateLocate::affine(const Mat& in, Mat& out, const double slope) +{ + //imshow("in", in); + //waitKey(0); + + Point2f dstTri[3]; + Point2f plTri[3]; + + int height = in.rows; + int width = in.cols; + double xiff = abs(slope) * height; + + if (slope > 0) + { + //ƫͣϵxiff/2λ + plTri[0] = Point2f(0, 0); + plTri[1] = Point2f(width - xiff - 1, 0); + plTri[2] = Point2f(0 + xiff, height - 1); + + dstTri[0] = Point2f(xiff / 2, 0); + dstTri[1] = Point2f(width - 1 - xiff / 2, 0); + dstTri[2] = Point2f(xiff/2, height - 1); + } + else + { + //ƫͣϵ -xiff/2λ + plTri[0] = Point2f(0 + xiff, 0); + plTri[1] = Point2f(width - 1, 0); + plTri[2] = Point2f(0, height - 1); + + dstTri[0] = Point2f(xiff/2, 0); + dstTri[1] = Point2f(width - 1 - xiff + xiff/2, 0); + dstTri[2] = Point2f(xiff/2, height - 1); + } + + /*dstTri[0] = Point2f(0, 0); + dstTri[1] = Point2f(WIDTH - 1, 0); + dstTri[2] = Point2f(0, HEIGHT - 1);*/ + + Mat warp_mat = getAffineTransform(plTri, dstTri); + + Mat affine_mat; + affine_mat.create(height, width, TYPE); + + if (in.rows > HEIGHT || in.cols > WIDTH) + warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_AREA); + else + warpAffine(in, affine_mat, warp_mat, affine_mat.size(), CV_INTER_CUBIC); + + out = affine_mat; + + /*imshow("out", out); + waitKey(0);*/ +} + + +//! һȫRect +//! ڣfalse +bool CPlateLocate::calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rect_& safeBoundRect) +{ + Rect_ boudRect = roi_rect.boundingRect(); - if(( area < min || area > max ) || ( r < rmin || r > rmax )) - { + // boudRectϵxyпС0 + float tl_x = boudRect.x > 0 ? boudRect.x : 0; + float tl_y = boudRect.y > 0 ? boudRect.y : 0; + // boudRectµxyпܴsrcķΧ + float br_x = boudRect.x + boudRect.width < src.cols ? + boudRect.x + boudRect.width - 1 : src.cols - 1; + float br_y = boudRect.y + boudRect.height < src.rows ? + boudRect.y + boudRect.height - 1 : src.rows - 1; + + float roi_width = br_x - tl_x; + float roi_height = br_y - tl_y; + + if (roi_width <= 0 || roi_height <= 0) return false; + + // ½һmatȷַԽ磬Էmatλroiʱ쳣 + safeBoundRect = Rect_(tl_x, tl_y, roi_width, roi_height); + + return true; +} + + + +int CPlateLocate::colorJudge(const Mat& src, const Color r, vector& rects) +{ + Mat src_hsv; + Mat src_color; + cvtColor(src, src_hsv, CV_BGR2HSV); + + vector hsvSplit; + split(src_hsv, hsvSplit); + + Mat h_mat = hsvSplit[2]; + + //blueHΧ + const int min_blue = 100; + const int max_blue = 140; + + //yellowHΧ + const int min_yellow = 15; + const int max_yellow = 40; + + //ƥģɫ,лԲҪĻɫ + int min_h = 0; + int max_h = 0; + switch (r) { + case BLUE: + min_h = min_blue; + max_h = max_blue; + break; + case YELLOW: + min_h = min_yellow; + max_h = max_yellow; + break; } - else + + Mat src_threshold; + double thresh = threshold(h_mat, src_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + + Mat element = getStructuringElement(MORPH_RECT, Size(5, 3)); + morphologyEx(src_threshold, src_threshold, MORPH_CLOSE, element); + + if (1){ + imshow("color", src); + waitKey(0); + imshow("color", src_threshold); + waitKey(0); + } + + vector< vector< Point> > contours; + findContours(src_threshold, + contours, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + + vector>::iterator itc = contours.begin(); + + while (itc != contours.end()) { - return true; + RotatedRect mr = minAreaRect(Mat(*itc)); + if (!verifySizes(mr)) + { + itc = contours.erase(itc); + } + else + { + ++itc; + rects.push_back(mr); + } } + return 0; + } -//! ʾɵijͼ񣬱жǷɹת -Mat CPlateLocate::showResultMat(Mat src, Size rect_size, Point2f center, int index) + +int CPlateLocate::deskewOld(Mat src, vector& inRects, + vector& outRects, vector& outMats, LocateType locateType) { - Mat img_crop; + int k = 1; + for(int i=0; i< inRects.size(); i++) + { + RotatedRect minRect = inRects[i]; - getRectSubPix(src, rect_size, center, img_crop); + if(verifySizes(minRect)) + { + float r = (float)minRect.size.width / (float)minRect.size.height; + float angle = minRect.angle; + cout << "angle:" << angle << endl; - if(m_debug) - { - stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/debug_crop_" << index << ".jpg"; - imwrite(ss.str(), img_crop); + Size rect_size = minRect.size; + if (r < 1) { + angle = 90 + angle; + swap(rect_size.width, rect_size.height); + } + + if (angle - m_angle < 0 && angle + m_angle > 0) + { + Rect_ boudRect = minRect.boundingRect(); + + // boudRectϵxyпС0 + float tl_x = boudRect.x > 0 ? boudRect.x : 0; + float tl_y = boudRect.y > 0 ? boudRect.y : 0; + // boudRectϵxyпܴsrcķΧ + float br_x = boudRect.x + boudRect.width < src.cols ? + boudRect.x + boudRect.width - 1 : src.cols - 1; + float br_y = boudRect.y + boudRect.height < src.rows ? + boudRect.y + boudRect.height - 1 : src.rows - 1; + + float roi_width = br_x - tl_x; + float roi_height = br_y - tl_y; + + if (roi_width <= 0 || roi_height <= 0) + continue; + + // ½һmatȷַԽ磬Էmatλroiʱ쳣 + Rect_ roiRect = Rect_(tl_x, tl_y, roi_width, roi_height); + + Mat src_mat = src(roiRect); + + //imshow("src_mat", src_mat); + //waitKey(0); + + if (locateType == COLOR) + { + Mat img_crop; + if (0.0 == angle || 90.0 == angle || -90.0 == angle || -0.0 == angle) + { + // ǶȵЩֵҪתֱӾ + // תüеԲֵģ + img_crop = src_mat; + } + else if (angle - 5 < 0 && angle + 5 > 0) + { + // ǶС5ȣ򲻱תֱʾ + // תüеԲֵģ + img_crop = src_mat; + } + else + { + // Ƕ5ȵ45֮䣬Ҫת + + //vector rects_tmp; + //deskewP(src_mat, BLUE, rects_tmp); + + Point2f newcenter(roiRect.width / 2, roiRect.height / 2 ); + /*cout << "a:" << angle;*/ + Mat rotmat = getRotationMatrix2D(newcenter, angle, 1); + + Mat img_rotated; + warpAffine(src_mat, img_rotated, rotmat, src_mat.size(), CV_INTER_CUBIC); + + /*imshow("img_rotated", img_rotated); + waitKey(0); +*/ + Mat middle_crop; + getRectSubPix(img_rotated, rect_size, newcenter, middle_crop); + + /*imshow("middle_crop", middle_crop); + waitKey(0);*/ + + if (r <= 10) + { + Point2f srcTri[4]; + Point2f dstTri[3]; + + Point2f plTri[3]; + + if (angle < 0) + { + double PI = 3.14159265; + double g = tan((angle + 90) * PI / 180.0); + + double xdiff = double(middle_crop.rows) * g; + plTri[0] = Point2f(0 + xdiff, 0); + plTri[1] = Point2f(middle_crop.cols - 1, 0); + plTri[2] = Point2f(0 , middle_crop.rows - 1); + } + else + { + double PI = 3.14159265; + double g = tan(abs(angle) * PI / 180.0); + + double xdiff = double(middle_crop.rows) * g; + plTri[0] = Point2f(0, 0); + plTri[1] = Point2f(middle_crop.cols - 1, 0); + plTri[2] = Point2f(0 + xdiff, middle_crop.rows - 1); + } + + dstTri[0] = Point2f(0, 0); + dstTri[1] = Point2f(WIDTH - 1, 0); + dstTri[2] = Point2f(0, HEIGHT - 1); + + // + Mat warp_mat = getAffineTransform(plTri, dstTri); + ////Mat warp_mat = getPerspectiveTransform( srcTri, dstTri ); + Mat result_crop; + warpAffine(middle_crop, result_crop, warp_mat, Size(WIDTH, HEIGHT), CV_INTER_CUBIC); + + result_crop.copyTo(img_crop); + + /*imshow("img_crop", img_crop); + waitKey(0);*/ + } + else + { + img_crop = middle_crop; + } + + } + + if (sobelJudge(img_crop)) { + + Mat plate_img; + plate_img.create(HEIGHT, WIDTH, TYPE); + if (img_crop.cols >= WIDTH || img_crop.rows >= HEIGHT) + resize(img_crop, plate_img, plate_img.size(), 0, 0, INTER_AREA); + else + resize(img_crop, plate_img, plate_img.size(), 0, 0, INTER_CUBIC); + + /*imshow("plate_img", plate_img); + waitKey(0);*/ + + outRects.push_back(minRect); + outMats.push_back(plate_img); + } + } + + if (locateType == SOBEL) { + vector resultVec; + vector resultRects; + sobelFindAgn(src_mat, resultRects, resultVec); + + for (int j = 0; j < resultRects.size(); j++) { + Point2f origin_center = Point2f(tl_x, tl_y) + resultRects[j].center; + RotatedRect origin_rect(origin_center, resultRects[j].size, resultRects[j].angle); + outRects.push_back(origin_rect); + } + + for (int j = 0; j < resultVec.size(); j++) + { + //if (charJudge(resultVec[j])) + outMats.push_back(resultVec[j]); + } + } + + } + } } - Mat resultResized; - resultResized.create(HEIGHT, WIDTH, TYPE); + return 0; +} - resize(img_crop, resultResized, resultResized.size(), 0, 0, INTER_CUBIC); - if(m_debug) - { - stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/debug_resize_" << index << ".jpg"; - imwrite(ss.str(), resultResized); +// !ɫϢijƶλ +int CPlateLocate::plateColorLocate(Mat src, vector& candPlates, int index) +{ + vector rects_color_blue; + vector rects_color_yellow; + vector plates; + Mat src_b; + + // ɫ + // ɫƥ䳵 + colorMatch(src, BLUE, src_b, rects_color_blue, index); + // пŤб + deskew(src, src_b, rects_color_blue, plates); + + // һɫ + colorMatch(src, YELLOW, src_b, rects_color_yellow, index); + deskew(src, src_b, rects_color_yellow, plates); + + for (int i = 0; i< plates.size(); i++) + candPlates.push_back(plates[i]); + + return 0; +} + + +// !ڴֱijƶλ +int CPlateLocate::plateSobelLocate(Mat src, vector& candPlates, int index) +{ + vector rects_sobel; + vector rects_sobel_sel; + vector plates; + + vector> bound_rects; + + // Sobelһδ + sobelFrtSearch(src, bound_rects); + + for (int i = 0; i < bound_rects.size(); i++) + { + Rect_ bound_rect = bound_rects[i]; + Point2f refpoint(bound_rect.x, bound_rect.y); + + int x = bound_rect.x > 0 ? bound_rect.x : 0; + int y = bound_rect.y > 0 ? bound_rect.y : 0; + + int width = x + bound_rect.width < src.cols ? bound_rect.width : src.cols - x; + int height = y + bound_rect.height < src.rows ? bound_rect.height : src.rows - y; + + Rect safe_bound_rect(x, y, width, height); + Mat bound_mat = src(safe_bound_rect); + + // Sobelڶξϸ + sobelSecSearch(bound_mat, refpoint, rects_sobel); } - return resultResized; + Mat src_b; + sobelOper(src, src_b, 3, 10, 3); + + // пŤб + deskew(src, src_b, rects_sobel, plates); + + for (int i = 0; i< plates.size(); i++) + candPlates.push_back(plates[i]); + + return 0; } +// Point2f srcTri[3]; +// Point2f dstTri[3]; +// +// Point2f rect_points[4]; +// minRect.points( rect_points ); +// +// for(int i = 0; i < 4; i++) +// rect_points[i] -= bouding.tl(); +// +// for(int i = 0; i < 3; i++) { +// for(int j = 0; j < 3-i; j++) { +// if (rect_points[j].x > rect_points[j+1].x) { +// Point2f t = rect_points[j]; +// rect_points[j] = rect_points[j+1]; +// rect_points[j+1] = t; +// } +// } +// } +// +// if (rect_points[0].y < rect_points[1].y) { +// srcTri[0] = rect_points[0]; +// srcTri[2] = rect_points[1]; +// } else { +// srcTri[0] = rect_points[1]; +// srcTri[2] = rect_points[0]; +// } + + + + +//! deprected //! λͼ //! src ԭʼͼ //! resultVec һMat洢ץȡͼ //! ɹ0򷵻-1 -int CPlateLocate::plateLocate(Mat src, vector& resultVec) +//int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) +//{ +// Mat src_blur, src_gray; +// Mat grad; +// Mat src_hist; +// Mat src_color; +// +// int scale = SOBEL_SCALE; +// int delta = SOBEL_DELTA; +// int ddepth = SOBEL_DDEPTH; +// +// if( !src.data ) +// { return -1; } +// +// //ԣͨΪͨ +// //vector channels; +// //split(src, channels); +// //Mat imageBlue = channels.at(0); +// //if(1) +// //{ +// // stringstream ss(stringstream::in | stringstream::out); +// // ss << "image/tmp/debug_imageBlue" << index << ".jpg"; +// // imwrite(ss.str(), imageBlue); +// //} +// +// //˹ģSizeеӰ쳵ƶλЧ +// GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), +// 0, 0, BORDER_DEFAULT ); +// +// if(m_debug) +// { +// stringstream ss(stringstream::in | stringstream::out); +// ss << "image/tmp/debug_GaussianBlur" << ".jpg"; +// imwrite(ss.str(), src_blur); +// } +// +// /// Convert it to gray +// cvtColor( src_blur, src_gray, CV_RGB2GRAY ); +// +// if(m_debug) +// { +// stringstream ss(stringstream::in | stringstream::out); +// ss << "image/tmp/debug_gray" << ".jpg"; +// imwrite(ss.str(), src_gray); +// } +// +// /// Generate grad_x and grad_y +// Mat grad_x, grad_y; +// Mat abs_grad_x, abs_grad_y; +// +// /// Gradient X +// //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); +// Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); +// convertScaleAbs( grad_x, abs_grad_x ); +// +// /// Gradient Y +// //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); +// Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); +// convertScaleAbs( grad_y, abs_grad_y ); +// +// /// Total Gradient (approximate) +// addWeighted( abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad ); +// +// //Laplacian( src_gray, grad_x, ddepth, 3, scale, delta, BORDER_DEFAULT ); +// //convertScaleAbs( grad_x, grad ); +// +// if(m_debug) +// { +// stringstream ss(stringstream::in | stringstream::out); +// //ss << "image/tmp/debug_Sobel_" << index << ".jpg"; +// ss << "image/tmp/" << index << "_" << 3 <<"_debug_Sobel" << ".jpg"; +// imwrite(ss.str(), grad); +// } +// +// //if(1) +// //{ +// // stringstream ss(stringstream::in | stringstream::out); +// // ss << "image/tmp/" << index << "_" << 4 <<"_src_combin" << ".jpg"; +// // imwrite(ss.str(), src_combin); +// //} +// +// Mat img_threshold; +// threshold(grad, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); +// +// if(0) +// { +// stringstream ss(stringstream::in | stringstream::out); +// //ss << "image/tmp/debug_threshold_" << index << ".jpg"; +// ss << "image/tmp/" << index << "_" << 5 <<"_img_threshold" << ".jpg"; +// imwrite(ss.str(), img_threshold); +// } +// +// Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight) ); +// morphologyEx(img_threshold, img_threshold, MORPH_CLOSE, element); +// +// if(1) +// { +// stringstream ss(stringstream::in | stringstream::out); +// //ss << "image/tmp/debug_morphology_" << index << ".jpg"; +// ss << "image/tmp/" << index << "_" << 6 <<"_morph" << ".jpg"; +// imwrite(ss.str(), img_threshold); +// } +// +// //Find of possibles plates +// vector< vector< Point> > contours; +// findContours(img_threshold, +// contours, // a vector of contours +// CV_RETR_EXTERNAL, // ȡⲿ +// CV_CHAIN_APPROX_NONE); // all pixels of each contours +// +// Mat result; +// if(1) +// { +// //// Draw blue contours on a white image +// src.copyTo(result); +// +// //drawContours(result, contours, +// // -1, // draw all contours +// // Scalar(0,0,255), // in blue +// // 1); // with a thickness of 1 +// +// //stringstream ss(stringstream::in | stringstream::out); +// //ss << "image/tmp/debug_Contours" << ".jpg"; +// //imwrite(ss.str(), result); +// } +// +// +// //Start to iterate to each contour founded +// vector >::iterator itc = contours.begin(); +// +// vector rects; +// //Remove patch that are no inside limits of aspect ratio and area. +// int t = 0; +// while (itc != contours.end()) +// { +// //Create bounding rect of object +// RotatedRect mr = minAreaRect(Mat(*itc)); +// +// //large the rect for more +// if( !verifySizes(mr)) +// { +// itc = contours.erase(itc); +// } +// else +// { +// ++itc; +// rects.push_back(mr); +// } +// } +// +// int k = 1; +// for(int i=0; i< rects.size(); i++) +// { +// RotatedRect minRect = rects[i]; +// if(verifySizes(minRect)) +// { +// // rotated rectangle drawing +// // Get rotation matrix +// // תⲿִȷʵԽijЩбijƵ +// // Ҳ󽫸ijƸбۺϿǣDzʹδ롣 +// // 2014-08-14,µһͼƬзкܶ೵бģ˾ٴγ +// // δ롣 +// float r = (float)minRect.size.width / (float)minRect.size.height; +// float angle = minRect.angle; +// Size rect_size = minRect.size; +// if (r < 1) +// { +// angle = 90 + angle; +// swap(rect_size.width, rect_size.height); +// } +// //ץȡķתm_angleǶȣdzƣ +// if (angle - m_angle < 0 && angle + m_angle > 0) +// { +// if(1) +// { +// Point2f rect_points[4]; +// minRect.points( rect_points ); +// for( int j = 0; j < 4; j++ ) +// line( result, rect_points[j], rect_points[(j+1)%4], Scalar(0,255,255), 1, 8 ); +// } +// +// //Create and rotate image +// Mat rotmat = getRotationMatrix2D(minRect.center, angle, 1); +// Mat img_rotated; +// +// /*if(m_debug) +// { +// stringstream ss(stringstream::in | stringstream::out); +// ss << "image/tmp/needRotate" << i << ".jpg"; +// imwrite(ss.str(), result); +// }*/ +// +// warpAffine(src, img_rotated, rotmat, src.size(), CV_INTER_CUBIC); +// +// /*if(m_debug) +// { +// stringstream ss(stringstream::in | stringstream::out); +// ss << "image/tmp/img_rotated" << i << ".jpg"; +// imwrite(ss.str(), result); +// }*/ +// +// +// //Mat resultMat(img_rotated, minRect); +// Mat resultMat; +// resultMat = showResultMat(img_rotated, rect_size, minRect.center, k++); +// +// resultVec.push_back(resultMat); +// } +// } +// } +// +// if(1) +// { +// stringstream ss(stringstream::in | stringstream::out); +// //ss << "image/tmp/debug_result" << ".jpg"; +// ss << "image/tmp/" << index << "_" << 9 <<"_result" << ".jpg"; +// imwrite(ss.str(), result); +// } +// +// return 0; +//} + + +//! µĶλͼ +//! ɹ +//! ɫϢSobelϢж +//! src ԭʼͼ +//! resultVec һMat洢ץȡͼ +//! ɹ0򷵻-1 +int CPlateLocate::plateLocate(Mat src, vector& resultVec, int index) { Mat src_blur, src_gray; Mat grad; @@ -127,29 +1768,158 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) int delta = SOBEL_DELTA; int ddepth = SOBEL_DDEPTH; - if( !src.data ) - { return -1; } + if (!src.data) + { + return -1; + } //˹ģSizeеӰ쳵ƶλЧ - GaussianBlur( src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), - 0, 0, BORDER_DEFAULT ); + GaussianBlur(src, src_blur, Size(m_GaussianBlurSize, m_GaussianBlurSize), + 0, 0, BORDER_DEFAULT); - if(m_debug) - { + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); ss << "image/tmp/debug_GaussianBlur" << ".jpg"; imwrite(ss.str(), src_blur); } /// Convert it to gray - cvtColor( src_blur, src_gray, CV_RGB2GRAY ); + cvtColor(src_blur, src_gray, CV_RGB2GRAY); - if(m_debug) - { + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); ss << "image/tmp/debug_gray" << ".jpg"; imwrite(ss.str(), src_gray); } + // RGBɫλ + // http://wenku.baidu.com/view/2329e5d2360cba1aa811da65.html?re=view + // RGB -> HSV + // + //H 200~255 25~55 / / + //S 0.4~1 0.4~1 0~0.1 / + //V 0.3~1 0.3~1 0.9~1 0~0.35 + //cvCvtColor(src,dst,CV_BGR2HSV); + //УsrcΪͨģdstҲΪͨģ + //OPENCV HSV˳ֱΪ3*x+0 3*x+1 3*x+2 + //opencvе H 0~180 S0~255 V0~255 + //HSVɫռȴ涨ǣHΧ0~360SΧ0~1VΧ0~1 + //ҪԼתһ£H*2S/255, V/255 + + // Ĭɫ + cv::Mat tmp; + cv::cvtColor(src, tmp, CV_BGR2HSV); + vector hsvSplit; + split(tmp, hsvSplit); + cv::Mat dst_blue(src.rows, src.cols, CV_8UC1); + cv::Mat dst_yellow(src.rows, src.cols, CV_8UC1); + for (int i = 0; i(i, j) * 2; + float fS = hsvSplit[1].at(i, j) / 255.0; + float fV = hsvSplit[2].at(i, j) / 255.0; + if (nH >= 200 && nH <= 255 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // ɫ + dst_blue.at(i, j) = 255; + else + dst_blue.at(i, j) = 0; + } + } + Mat element_blue = getStructuringElement(MORPH_ELLIPSE, Size(10, 10)); + morphologyEx(dst_blue, dst_blue, MORPH_CLOSE, element_blue); + //Find of possibles plates + cv::Mat con_blue = dst_blue.clone(); + vector< vector< Point> > contours_blue; + findContours(con_blue, + contours_blue, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + //Start to iterate to each contour founded + vector >::iterator itb = contours_blue.begin(); + + //Remove patch that are no inside limits of aspect ratio and area. + int tb = 0; + vector rects_blue; + while (itb != contours_blue.end()) + { + //Create bounding rect of object + RotatedRect mr = minAreaRect(Mat(*itb)); + + Rect_ safeBoundRect; + if (!calcSafeRect(mr, src, safeBoundRect)) + { + itb++; + continue; + } + + //large the rect for more + if (!verifySizes(mr)) + { + cv::Mat& roi = dst_blue(safeBoundRect); + roi.setTo(0); + } + else + { + rects_blue.push_back(safeBoundRect); + } + ++itb; + } + ////////////////////////////////////////////////////////////////////////// + for (int i = 0; i(i, j) * 2; + float fS = hsvSplit[1].at(i, j) / 255.0; + float fV = hsvSplit[2].at(i, j) / 255.0; + if (nH >= 25 && nH <= 55 && fS >= 0.4 && fS <= 1 && fV >= 0.3 && fV <= 1) // ɫ + dst_yellow.at(i, j) = 255; + else + dst_yellow.at(i, j) = 0; + } + } + + Mat element_yellow = getStructuringElement(MORPH_ELLIPSE, Size(10, 10)); + morphologyEx(dst_yellow, dst_yellow, MORPH_CLOSE, element_blue); + //Find of possibles plates + cv::Mat con_yellow = dst_yellow.clone(); + vector< vector< Point> > contours_yellow; + findContours(con_yellow, + contours_yellow, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + //Start to iterate to each contour founded + vector >::iterator ity = contours_yellow.begin(); + + //Remove patch that are no inside limits of aspect ratio and area. + tb = 0; + vector rects_yellow; + while (ity != contours_yellow.end()) + { + //Create bounding rect of object + RotatedRect mr = minAreaRect(Mat(*ity)); + + Rect_ safeBoundRect; + if (!calcSafeRect(mr, src, safeBoundRect)) + { + ity++; + continue; + } + + //large the rect for more + if (!verifySizes(mr)) + { + cv::Mat& roi = dst_yellow(safeBoundRect); + roi.setTo(0); + } + else + { + rects_yellow.push_back(safeBoundRect); + } + ++ity; + } /// Generate grad_x and grad_y Mat grad_x, grad_y; @@ -157,64 +1927,84 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) /// Gradient X //Scharr( src_gray, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT ); - Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT ); - convertScaleAbs( grad_x, abs_grad_x ); + Sobel(src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_x, abs_grad_x); /// Gradient Y //Scharr( src_gray, grad_y, ddepth, 0, 1, scale, delta, BORDER_DEFAULT ); - Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT ); - convertScaleAbs( grad_y, abs_grad_y ); + Sobel(src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT); + convertScaleAbs(grad_y, abs_grad_y); /// Total Gradient (approximate) - addWeighted( abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad ); + addWeighted(abs_grad_x, SOBEL_X_WEIGHT, abs_grad_y, SOBEL_Y_WEIGHT, 0, grad); //Laplacian( src_gray, grad_x, ddepth, 3, scale, delta, BORDER_DEFAULT ); - //convertScaleAbs( grad_x, grad ); - - - if(m_debug) - { + //convertScaleAbs( grad_x, grad ); + cv::Mat out_blue; + cv::multiply(grad, dst_blue, out_blue); + cv::Mat out_yellow; + cv::multiply(grad, dst_yellow, out_yellow); + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/debug_Sobel" << ".jpg"; - imwrite(ss.str(), grad); + ss << "image/tmp/debug_Sobel_blue" << ".jpg"; + imwrite(ss.str(), out_blue); + ss << "image/tmp/debug_Sobel_yellow" << ".jpg"; + imwrite(ss.str(), out_yellow); } - Mat img_threshold; - threshold(grad, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY); + Mat img_threshold_blue; + Mat img_threshold_yellow; + threshold(out_blue, img_threshold_blue, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); + threshold(out_yellow, img_threshold_yellow, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); //threshold(grad, img_threshold, 75, 255, CV_THRESH_BINARY); - if(m_debug) - { + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/debug_threshold" << ".jpg"; - imwrite(ss.str(), img_threshold); + ss << "image/tmp/debug_threshold_blue" << ".jpg"; + imwrite(ss.str(), img_threshold_blue); + ss << "image/tmp/debug_threshold_yellow" << ".jpg"; + imwrite(ss.str(), img_threshold_yellow); } - Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight) ); - morphologyEx(img_threshold, img_threshold, MORPH_CLOSE, element); - - if(m_debug) - { + Mat element = getStructuringElement(MORPH_RECT, Size(m_MorphSizeWidth, m_MorphSizeHeight)); + morphologyEx(img_threshold_blue, img_threshold_blue, MORPH_CLOSE, element); + morphologyEx(img_threshold_yellow, img_threshold_yellow, MORPH_CLOSE, element); + + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/debug_morphology" << ".jpg"; - imwrite(ss.str(), img_threshold); + ss << "image/tmp/debug_morphology_blue" << ".jpg"; + imwrite(ss.str(), img_threshold_blue); + ss << "image/tmp/debug_morphology_yellow" << ".jpg"; + imwrite(ss.str(), img_threshold_yellow); } //Find of possibles plates - vector< vector< Point> > contours; - findContours(img_threshold, - contours, // a vector of contours + contours_blue.clear(); + findContours(img_threshold_blue, + contours_blue, // a vector of contours + CV_RETR_EXTERNAL, // ȡⲿ + CV_CHAIN_APPROX_NONE); // all pixels of each contours + contours_yellow.clear(); + findContours(img_threshold_yellow, + contours_yellow, // a vector of contours CV_RETR_EXTERNAL, // ȡⲿ CV_CHAIN_APPROX_NONE); // all pixels of each contours Mat result; - if(m_debug) - { + if (m_debug) + { //// Draw blue contours on a white image src.copyTo(result); - drawContours(result, contours, + drawContours(result, contours_blue, + -1, // draw all contours + Scalar(0, 0, 255), // in blue + 1); // with a thickness of 1 + drawContours(result, contours_yellow, -1, // draw all contours - Scalar(0,0,255), // in blue + Scalar(0, 0, 255), // in blue 1); // with a thickness of 1 stringstream ss(stringstream::in | stringstream::out); ss << "image/tmp/debug_Contours" << ".jpg"; @@ -223,46 +2013,63 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) //Start to iterate to each contour founded - vector >::iterator itc = contours.begin(); - + itb = contours_blue.begin(); + vector rects; //Remove patch that are no inside limits of aspect ratio and area. int t = 0; - while (itc != contours.end()) + while (itb != contours_blue.end()) { //Create bounding rect of object - RotatedRect mr = minAreaRect(Mat(*itc)); + RotatedRect mr = minAreaRect(Mat(*itb)); //large the rect for more - if( !verifySizes(mr)) + if (!verifySizes(mr)) { - itc = contours.erase(itc); + itb = contours_blue.erase(itb); } else { - ++itc; + ++itb; rects.push_back(mr); } } + ity = contours_yellow.begin(); + while (ity != contours_yellow.end()) + { + //Create bounding rect of object + RotatedRect mr = minAreaRect(Mat(*ity)); + + //large the rect for more + if (!verifySizes(mr)) + { + ity = contours_yellow.erase(ity); + } + else + { + ++ity; + rects.push_back(mr); + } + } int k = 1; - for(int i=0; i< rects.size(); i++) + for (int i = 0; i< rects.size(); i++) { RotatedRect minRect = rects[i]; - if(verifySizes(minRect)) - { + if (verifySizes(minRect)) + { // rotated rectangle drawing // Get rotation matrix // תⲿִȷʵԽijЩбijƵ // Ҳ󽫸ijƸбۺϿǣDzʹδ롣 // 2014-08-14,µһͼƬзкܶ೵бģ˾ٴγ // δ롣 - if(m_debug) - { - Point2f rect_points[4]; - minRect.points( rect_points ); - for( int j = 0; j < 4; j++ ) - line( result, rect_points[j], rect_points[(j+1)%4], Scalar(0,255,255), 1, 8 ); + if (m_debug) + { + Point2f rect_points[4]; + minRect.points(rect_points); + for (int j = 0; j < 4; j++) + line(result, rect_points[j], rect_points[(j + 1) % 4], Scalar(0, 255, 255), 1, 8); } float r = (float)minRect.size.width / (float)minRect.size.height; @@ -279,25 +2086,8 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) //Create and rotate image Mat rotmat = getRotationMatrix2D(minRect.center, angle, 1); Mat img_rotated; - - /*if(m_debug) - { - stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/needRotate" << i << ".jpg"; - imwrite(ss.str(), result); - }*/ - warpAffine(src, img_rotated, rotmat, src.size(), CV_INTER_CUBIC); - /*if(m_debug) - { - stringstream ss(stringstream::in | stringstream::out); - ss << "image/tmp/img_rotated" << i << ".jpg"; - imwrite(ss.str(), result); - }*/ - - - //Mat resultMat(img_rotated, minRect); Mat resultMat; resultMat = showResultMat(img_rotated, rect_size, minRect.center, k++); @@ -306,8 +2096,8 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) } } - if(m_debug) - { + if (m_debug) + { stringstream ss(stringstream::in | stringstream::out); ss << "image/tmp/debug_result" << ".jpg"; imwrite(ss.str(), result); @@ -316,4 +2106,7 @@ int CPlateLocate::plateLocate(Mat src, vector& resultVec) return 0; } + + + } /*! \namespace easypr*/ \ No newline at end of file diff --git a/src/core/plate_recognize.cpp b/src/core/plate_recognize.cpp index 0a614bf..ceecebc 100644 --- a/src/core/plate_recognize.cpp +++ b/src/core/plate_recognize.cpp @@ -38,10 +38,15 @@ CPlateRecognize::CPlateRecognize() int CPlateRecognize::plateRecognize(Mat src, vector& licenseVec) { - //Ʒ鼯 + // Ʒ鼯 vector plateVec; + + // DebugģʽʾеͼƬ + bool showDetectArea = getPDDebug(); + + // ȶλʹɫϢSobel + int resultPD = plateDetectDeep(src, plateVec, showDetectArea, 0); - int resultPD = plateDetect(src, plateVec); if (resultPD == 0) { int num = plateVec.size(); diff --git a/src/include/chars_segment.h b/src/include/chars_segment.h index ed1c40f..f1a14a5 100644 --- a/src/include/chars_segment.h +++ b/src/include/chars_segment.h @@ -22,7 +22,10 @@ namespace easypr { class CCharsSegment { public: + enum Color { BLUE, YELLOW }; + CCharsSegment(); + bool plateColorJudge(Mat src, Color r); //! ַָ int charsSegment(Mat, vector& ); diff --git a/src/include/plate.h b/src/include/plate.h new file mode 100644 index 0000000..40d15bd --- /dev/null +++ b/src/include/plate.h @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////// +// Name: plate Header +// Version: 1.0 +// Date: 2015-03-12 +// Author: liuruoze +// Copyright: liuruoze +// Desciption: +// Defines CPlate +////////////////////////////////////////////////////////////////////////// +#ifndef __PLATE_H__ +#define __PLATE_H__ + +#include "prep.h" + +/*! \namespace easypr +Namespace where all the C++ EasyPR functionality resides +*/ +namespace easypr { + + class CPlate + { + public: + CPlate(); + + //! ȡ + inline void setPlateMat(Mat param){ m_plateMat = param; } + inline Mat getPlateMat() const{ return m_plateMat; } + + inline void setPlatePos(RotatedRect param){ m_platePos = param; } + inline RotatedRect getPlatePos() const{ return m_platePos; } + + inline void setPlateStr(String param){ m_plateStr = param; } + inline String getPlateStr() const{ return m_plateStr; } + + private: + //! Ƶͼ + Mat m_plateMat; + + //! ԭͼλ + RotatedRect m_platePos; + + //! ַ + String m_plateStr; + }; + +} /*! \namespace easypr*/ + +#endif /* endif __PLATE_H__ */ \ No newline at end of file diff --git a/src/include/plate_detect.h b/src/include/plate_detect.h index abe497f..2783e79 100644 --- a/src/include/plate_detect.h +++ b/src/include/plate_detect.h @@ -17,6 +17,7 @@ #include "plate_locate.h" #include "plate_judge.h" + /*! \namespace easypr Namespace where all the C++ EasyPR functionality resides */ @@ -28,7 +29,12 @@ public: CPlateDetect(); //! Ƽ⣺ƶλж - int plateDetect(Mat, vector&); + int plateDetect(Mat, vector&, int index = 0); + + //! ȳƼ⣬ʹɫSobelۺ + int plateDetectDeep(Mat src, vector& resultVec, bool showDetectArea = false, int index = 0); + + int showResult(const Mat& result); //! װSVMģ void LoadSVM(string s); diff --git a/src/include/plate_judge.h b/src/include/plate_judge.h index 388a98a..3c948c8 100644 --- a/src/include/plate_judge.h +++ b/src/include/plate_judge.h @@ -14,6 +14,7 @@ #include "prep.h" #include "features.h" +#include "plate.h" /*! \namespace easypr Namespace where all the C++ EasyPR functionality resides @@ -25,6 +26,9 @@ class CPlateJudge public: CPlateJudge(); + //! ԶƽSVMж + int plateJudge(const vector&, vector&); + //! ж int plateJudge(const vector&, vector&); diff --git a/src/include/plate_locate.h b/src/include/plate_locate.h index 61d94bc..d8837e3 100644 --- a/src/include/plate_locate.h +++ b/src/include/plate_locate.h @@ -14,6 +14,7 @@ #define __PLATE_LOCATE_H__ #include "prep.h" +#include "plate.h" /*! \namespace easypr Namespace where all the C++ EasyPR functionality resides @@ -25,8 +26,67 @@ class CPlateLocate public: CPlateLocate(); + enum LocateType { SOBEL, COLOR }; + enum Color { BLUE, YELLOW }; + + //! Sobelһ + //! ƴС״ȡBoundRectһ + int sobelFrtSearch(const Mat& src, vector>& outRects); + + //! Sobelڶ + //! ԴС״ƣɲο + int sobelSecSearch(const Mat& bound, Point2f refpoint, vector& outRects); + + //! Ťб + int deskew(const Mat& src, const Mat& src_b, vector& inRects, vector& outPlates); + + //! Ƿƫб + //! ֵͼжϽ + bool isdeflection(const Mat& in, const double angle, double& slope); + + //! Sobel + //! ɫͼֵͼ + int sobelOper(const Mat& in, Mat& out, int blurSize, int morphW, int morphH); + + //! һȫRect + bool calcSafeRect(const RotatedRect& roi_rect, const Mat& src, Rect_& safeBoundRect); + + //! ת + bool rotation(Mat& in, Mat& out, const Size rect_size, const Point2f center, const double angle); + + //! Ť + void affine(const Mat& in, Mat& out, const double slope); + + //! ɫλ + int plateColorLocate(Mat src, vector& candPlates, int index = 0); + + //! Sobelλ + int plateSobelLocate(Mat src, vector& candPlates, int index = 0); + + //! Color + int colorMatch(const Mat& src, const Color r, Mat& out, vector& outRects, int index = 0); + + //! δʹú + //! ʼ------------ + int sobelFind(const Mat& src, vector& rects); + int sobelFindAgn(const Mat& src, vector& outRects, vector& resultVec); + + bool charJudge(Mat roi); + bool sobelJudge(Mat roi); + int colorJudge(const Mat& src, const Color r, vector& rects); + + int deskewOld(Mat src, vector& inRects, vector& outRects, vector& outMats, LocateType locateType); + + bool verifyCharSizes(Mat r); + int getPlateType(Mat src); + bool plateColorJudge(Mat src, const Color r); + Mat clearLiuDing(Mat img); + + //! ------------ + //! δʹú + //! ƶλ - int plateLocate(Mat, vector& ); + int plateLocate(Mat, vector&, int = 0 ); //! Ƶijߴ֤ bool verifySizes(RotatedRect mr); @@ -70,8 +130,8 @@ public: static const int SOBEL_DDEPTH = CV_16S; static const int SOBEL_X_WEIGHT = 1; static const int SOBEL_Y_WEIGHT = 0 ; - static const int DEFAULT_MORPH_SIZE_WIDTH = 17; - static const int DEFAULT_MORPH_SIZE_HEIGHT = 3; + static const int DEFAULT_MORPH_SIZE_WIDTH = 17;//17 + static const int DEFAULT_MORPH_SIZE_HEIGHT = 3;//3 //! showResultMató static const int WIDTH = 136; @@ -79,11 +139,11 @@ public: static const int TYPE = CV_8UC3; //! verifySizeó - static const int DEFAULT_VERIFY_MIN = 3; - static const int DEFAULT_VERIFY_MAX = 20; + static const int DEFAULT_VERIFY_MIN = 1;//3 + static const int DEFAULT_VERIFY_MAX = 24;//20 //! Ƕжó - static const int DEFAULT_ANGLE = 30; + static const int DEFAULT_ANGLE = 60;//30 //! ǷģʽĬ0ر static const int DEFAULT_DEBUG = 0; diff --git a/src/include/prep.h b/src/include/prep.h index 97ee7fb..7f16676 100644 --- a/src/include/prep.h +++ b/src/include/prep.h @@ -12,10 +12,12 @@ #include #include #include +#include #include #include #include #include +#include using namespace std; using namespace cv; diff --git a/src/test/accuracy_test.cpp b/src/test/accuracy_test.cpp index 9ebfdeb..e537691 100644 --- a/src/test/accuracy_test.cpp +++ b/src/test/accuracy_test.cpp @@ -20,6 +20,11 @@ int acurayTest(const string& test_path) pr.LoadANN("model/ann.xml"); pr.LoadSVM("model/svm.xml"); pr.setLifemode(true); + pr.setDebug(false); + + //CPlateDetect pd; + //pd.LoadSVM("model/svm.xml"); + //pd.setPDLifemode(true); int size = files.size(); //int size = 200; @@ -48,6 +53,10 @@ int acurayTest(const string& test_path) // ȫƥʶռʶͼƬеı float match_rate = 0; + // ʼͽʱ + time_t begin, end; + time(&begin); + for (int i = 0; i < size; i++) { string filepath = files[i].c_str(); @@ -56,11 +65,11 @@ int acurayTest(const string& test_path) // ȡʵij string plateLicense = ""; getFileName(filepath, plateLicense); - cout << "ԭ:" << plateLicense << endl; // EasyPRʼжϳ Mat src = imread(filepath); + vector plateVec; int result = pr.plateRecognize(src, plateVec); if (result == 0) @@ -138,8 +147,10 @@ int acurayTest(const string& test_path) count_err++; } count_all++; + } - + time(&end); + cout << "------------------" << endl; cout << "Easypr accuracy test end!" << endl; cout << "------------------" << endl; @@ -151,7 +162,7 @@ int acurayTest(const string& test_path) float count_recogin = count_all - (count_err + count_norecogin); float count_rate = count_recogin / count_all; float count_norate = 1 - count_rate; - cout << "ʶ:" << count_rate * 100 << "% " << endl; + cout << "λ:" << count_rate * 100 << "% " << endl; diff_avg = diff_all / count_recogin; match_rate = match_count/ count_recogin * 100; @@ -159,9 +170,44 @@ int acurayTest(const string& test_path) cout << "ƽַ:" << diff_avg << ", "; cout << "ȫƥ:" << match_count << ", "; cout << "ȫƥ:" << match_rate << "% " << endl; + + + double seconds = difftime(end, begin); + double avgsec = seconds / double(count_all); + + cout << "ʱ:" << seconds << ", "; + cout << "ƽִʱ:" << avgsec << " " << endl; + cout << endl; cout << "------------------" << endl; + + ofstream myfile("run_accuracy.txt", ios::app); + if (myfile.is_open()) + { + time_t t = time(0); // get time now + struct tm * now = localtime(&t); + char buf[80]; + + strftime(buf, sizeof(buf), "%Y-%m-%d %X", now); + myfile << string(buf) << endl; + + myfile << "ͼƬ:" << count_all << ", "; + myfile << "δʶͼƬ:" << count_norecogin << ", "; + myfile << "λ:" << count_rate * 100 << "% " << endl; + myfile << "ƽַ:" << diff_avg << ", "; + myfile << "ȫƥ:" << match_count << ", "; + myfile << "ȫƥ:" << match_rate << "% " << endl; + myfile << "ʱ:" << seconds << ", "; + myfile << "ƽִʱ:" << avgsec << " " << endl; + myfile.close(); + } + else + cout << "Unable to open file"; + + return 0; + + return 0; } \ No newline at end of file diff --git a/src/test/test.cpp b/src/test/test.cpp index e135837..1eb7e6f 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -115,7 +115,7 @@ int test_plate_locate() { cout << "test_plate_locate" << endl; - Mat src = imread("image/plate_locate.jpg"); + Mat src = imread("image/P8BK60.jpg"); vector resultVec; CPlateLocate plate;