From 5a51c779c95384459d74601abfb4f433ddf0b297 Mon Sep 17 00:00:00 2001 From: fthmko Date: Wed, 23 Feb 2022 15:23:22 +0800 Subject: [PATCH 1/2] Use a PNG image as cursor --- src/ScreenCapLibrary/cursor.png | Bin 0 -> 981 bytes src/ScreenCapLibrary/utils.py | 45 ++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 src/ScreenCapLibrary/cursor.png diff --git a/src/ScreenCapLibrary/cursor.png b/src/ScreenCapLibrary/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..d850e99727493bc204f863893abefb49313d1eb7 GIT binary patch literal 981 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+0817mrBPlzi}!G8vZRjXD3 z8M9~4{{H>@wQJXaY$qqD-@kwV|NsB|`SU=oxw-l4*RO$GAlu5y>e;hrK=zq4XI{N} z1!O?Li4!M)jBVSt0m&mrj(q+4^}~k`pFVy1^XJdEZ{L85U%q_#;>C-2Fv!fzoI7`J zeSQ6tCr^Nu0>S6cpIu!+?tuVpZEc_lK%=&7*-}wa@%ZuMpFe*BrM`Uma`fm?h#DXp zs30^n)Z5#8-MV#9oeT_n_Ur+QTUb~?L^L!s-n@AO)PC#MEue_9vhs=*D<)5#3|9{n zH!?B;>QYox&?ZfjFU{ScYomKh%Hvaotw`}Iy#J7?6%coCY z=W*R%?%-^t&vpOjt-Ff+eC*1P{?x?&ie#8Iu^l1%v#KPoU8F;pyTSVsSb-fq_v? zjjiMW2WtYKF}JpK9P1mIIWc#BhydfT^>gv#Km`R25kXCzCjZ8akdmGm9CoZ53qKk@ zQmPO=a#Y>J<54JsiL;l`dZr0nnR~b%2~AE(`KaOH=jrP`{n4>?3d(xM+ScxVagKqW zlCznn-r4h~X@^s&X(_L-ZVuO$?vj%3$6jB)@bdKD*r;J(W@u`>U8A>qOUi~#hr}YA zu9~RsBcl*QBP&xgD+2><17jdL&D;7TiiX_$l+3hB+!~&X SH3Rb_1B0ilpUXO@geCy&c9IhS literal 0 HcmV?d00001 diff --git a/src/ScreenCapLibrary/utils.py b/src/ScreenCapLibrary/utils.py index d20ff11..16d9a97 100644 --- a/src/ScreenCapLibrary/utils.py +++ b/src/ScreenCapLibrary/utils.py @@ -17,9 +17,6 @@ import cv2 import numpy as np -cursor_x_list = [0, 8, 6, 14, 12, 4, 2, 0] -cursor_y_list = [0, 2, 4, 12, 14, 6, 8, 0] - def _norm_path(path): if not path: @@ -65,11 +62,43 @@ def resize_array(width, height, numpy_array, size_percentage): def draw_cursor(frame, mouse_x, mouse_y): - cursor_x = [x + mouse_x for x in cursor_x_list] - cursor_y = [y + mouse_y for y in cursor_y_list] - cursor_points = list(zip(cursor_x, cursor_y)) - cursor_points = np.array(cursor_points, 'int32') - cv2.fillPoly(frame, [cursor_points], color=[0, 255, 255]) + """ + Draw a PNG image as cursor. + """ + cur_path = os.path.join(os.path.dirname(__file__), "cursor.png") + cur_img = cv2.imread(cur_path, -1) + + alpha_mask = cur_img[:, :, 3] / 255.0 + img_overlay = cur_img[:, :, :3] + _overlay_image_alpha(frame, img_overlay, mouse_x, mouse_y, alpha_mask) + + +def _overlay_image_alpha(img, img_overlay, x, y, alpha_mask): + """Overlay `img_overlay` onto `img` at (x, y) and blend using `alpha_mask`. + + `alpha_mask` must have same HxW as `img_overlay` and values in range [0, 1]. + + [https://stackoverflow.com/a/45118011] use @Mateen Ulhaq's overlay method + """ + # Image ranges + y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0]) + x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1]) + + # Overlay ranges + y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y) + x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x) + + # Exit if nothing to do + if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o: + return + + # Blend overlay within the determined ranges + img_crop = img[y1:y2, x1:x2] + img_overlay_crop = img_overlay[y1o:y2o, x1o:x2o] + alpha = alpha_mask[y1o:y2o, x1o:x2o, np.newaxis] + alpha_inv = 1.0 - alpha + + img_crop[:] = alpha * img_overlay_crop + alpha_inv * img_crop def is_pygtk(screenshot_module): From ab32ceab06fdd7a9c4f3782936c0fa85b562b54a Mon Sep 17 00:00:00 2001 From: fthmko Date: Wed, 23 Feb 2022 15:38:52 +0800 Subject: [PATCH 2/2] Remove blank around cursor to improve accuracy --- src/ScreenCapLibrary/cursor.png | Bin 981 -> 651 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/ScreenCapLibrary/cursor.png b/src/ScreenCapLibrary/cursor.png index d850e99727493bc204f863893abefb49313d1eb7..6f78c99ee2ddfd7be08db5c38852494eaeebc002 100644 GIT binary patch delta 645 zcmV;00($+`2a5$RiBL{Q4GJ0x0000DNk~Le0000E0000K2nGNE0KEkaEC2ui0drDE zLIAGL9O;oE6MqSCNLh0L01m?d01m?e$8V@)0006YNklJD6tUi1Q!y;uR<;K zboGqFo0(k=-f`Yt9(Zu)-TlpsGrJ_6P9LGke@Z-^PJd4Vfxw4Gqw#cmc0YN&-skJ} zdO#^H)a&&p+vB_CbUI&*Mx);>%K}Tk-y3$j-OOMxXj!dRS|}6{&em$RlkM%pLU1@7 zwsbljmCNO{R4O6-?M`?H8Vm*sAyp_8J2-PId>uq1Tr3t5KCf1*3jV?Cx(P(@RsMP- zd-9Wfu~?``B%*4yn)dsB%5mI$GMQYUHk%E%SS&ulw51OahD>C+T#`^IL=uSvaX1{L z*=&+rE=T-+|9LbTJ%h)Nq*Ce9X0vgfPDiNN>wooH$z+lOyaKcFc$}|px7+D#Hv8rC z`E(HDPH{kwFbOf6%?z~DfvTHKCi6ZPi=B46-9IXoiihzvT&-58aE%ggEmWM(=WL}? zi9x6Vzl8W_I2`7|U@(Y7`2oLIzFDzSsl0^$^3LP&e1!M{Jc5OPjzl6vtJM;X26GV& zbWZUQFZT5qjD6z`%z6wfcr_l6%P>f6^AbL}w{R}BxTjs;B0drlJYyKfno6bKz|dYp fjJxAEAc&B^Mk!$Xpvvh;00000NkvXXu0mjfF~=V3 literal 981 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEa{HEjtmSN`?>!lvVtU&J%W50 z7^>757#dm_7=8hT8eT9klo~KFyh>nTu$sZZAYL$MSD+0817mrBPlzi}!G8vZRjXD3 z8M9~4{{H>@wQJXaY$qqD-@kwV|NsB|`SU=oxw-l4*RO$GAlu5y>e;hrK=zq4XI{N} z1!O?Li4!M)jBVSt0m&mrj(q+4^}~k`pFVy1^XJdEZ{L85U%q_#;>C-2Fv!fzoI7`J zeSQ6tCr^Nu0>S6cpIu!+?tuVpZEc_lK%=&7*-}wa@%ZuMpFe*BrM`Uma`fm?h#DXp zs30^n)Z5#8-MV#9oeT_n_Ur+QTUb~?L^L!s-n@AO)PC#MEue_9vhs=*D<)5#3|9{n zH!?B;>QYox&?ZfjFU{ScYomKh%Hvaotw`}Iy#J7?6%coCY z=W*R%?%-^t&vpOjt-Ff+eC*1P{?x?&ie#8Iu^l1%v#KPoU8F;pyTSVsSb-fq_v? zjjiMW2WtYKF}JpK9P1mIIWc#BhydfT^>gv#Km`R25kXCzCjZ8akdmGm9CoZ53qKk@ zQmPO=a#Y>J<54JsiL;l`dZr0nnR~b%2~AE(`KaOH=jrP`{n4>?3d(xM+ScxVagKqW zlCznn-r4h~X@^s&X(_L-ZVuO$?vj%3$6jB)@bdKD*r;J(W@u`>U8A>qOUi~#hr}YA zu9~RsBcl*QBP&xgD+2><17jdL&D;7TiiX_$l+3hB+!~&X SH3Rb_1B0ilpUXO@geCy&c9IhS