کمک در اندازه گیری طول و عرض یک شی در تصویر (باینری)
سلام خدمت همه دوستان گلم
از اونجایی که یک قسمت از پروژه من به image processing مروبوط میشه و من هم در این زمینه کاملا مبتدی هستم خواهشمند یاری دوستان حرفه ای در این زمینه هستم.
من یکسری عکس از برگ های مختلف گیاهان دارم و باید توسط پردازش تصویر بصورت اتوماتیک مقدار طول و عرض اونارو اندازه بگیرم.مشکل اینجاست که من در این زمینه تخصص ندارم از دوستانی که میتونند کمک کنند ممنون میشم راهنمایی بگیرم.
برای نمونه عکس زیر رو میزارم که بیشتر قابل درک باشه.
[IMG][/IMG]
سلام خدمت همه دوستان گلم
از اونجایی که یک قسمت از پروژه من به image processing مروبوط میشه و من هم در این زمینه کاملا مبتدی هستم خواهشمند یاری دوستان حرفه ای در این زمینه هستم.
من یکسری عکس از برگ های مختلف گیاهان دارم و باید توسط پردازش تصویر بصورت اتوماتیک مقدار طول و عرض اونارو اندازه بگیرم.مشکل اینجاست که من در این زمینه تخصص ندارم از دوستانی که میتونند کمک کنند ممنون میشم راهنمایی بگیرم.
برای نمونه عکس زیر رو میزارم که بیشتر قابل درک باشه.
[IMG][/IMG]
email:mohamadalijan@gmail.com
این چیزیکه من به ذهنم می رسه شما می خواین بلندترین طول(قطر) را به دست بیارین و سپس ضلع دیگه میشه خطی که عمود بر این قطر باشه. برای این کار می تونین به این صورت عمل کنین:
1- با داشتن مختصات x,y کانتور یا همون پیرامون برگ ابتدا مرکز ثقل اون رو به دست بیارین که میشه مثلا xc,yc
XX=X-xc
YY=Y-yc
2- تمام مختصات x,y را از این مقدار کم کنید. در این صورت مرکز ثقل شما هم اکنون 0و0 خواهد شد.
3- ماتریس کواریانس آن را به دست بیاورید که ماتریسی 2*2 خواهد شد. در متلب تابعش هست cov یا
[XX,YY]'*[XX,YY] را محاسبه کنید
' منظور ترانهاده است.
XX,YY دو ماتریس n*1 هستند.
با محاسبه بردارهای ویژه و مقادیر ویژه این ماتریس نهایی 2*2 جهت و مقدار بزرگی دو قطر موردنظر یافت می شود.
این چیزیکه من به ذهنم می رسه شما می خواین بلندترین طول(قطر) را به دست بیارین و سپس ضلع دیگه میشه خطی که عمود بر این قطر باشه. برای این کار می تونین به این صورت عمل کنین:
1- با داشتن مختصات x,y کانتور یا همون پیرامون برگ ابتدا مرکز ثقل اون رو به دست بیارین که میشه مثلا xc,yc
xx=x-xc
yy=y-yc
2- تمام مختصات x,y را از این مقدار کم کنید. در این صورت مرکز ثقل شما هم اکنون 0و0 خواهد شد.
3- ماتریس کواریانس آن را به دست بیاورید که ماتریسی 2*2 خواهد شد. در متلب تابعش هست cov یا
[xx,yy]'*[xx,yy] را محاسبه کنید
' منظور ترانهاده است.
Xx,yy دو ماتریس n*1 هستند.
با محاسبه بردارهای ویژه و مقادیر ویژه این ماتریس نهایی 2*2 جهت و مقدار بزرگی دو قطر موردنظر یافت می شود.
مهدی جان خیلی ممنون از راهنمایی خوبت،من تقریبا روش کلی کار دستم اومد ولی بعضی جاهاشو یکم گیج میزنم منظورتو از گزینه 2 که نوشتی درست متوجه نشدم ، این x و y بزرگ کدوم ماتریس میشه که من باید مختصات مرکز ثقل رو از اونا کم کنم؟و اینکه که گفتی با محاسبه بردارهای ویژه و مقادیر ویژه این ماتریس نهایی 2*2 جهت و مقدار بزرگی دو قطر موردنظر یافت می شود میشه اینجاشو یکم بیشتر توضیح بدی؟ دست گلت درد نکنه
X نشان دهنده مختصات x یا همون ستونهای پیکسل های پیرامونته که هست n*1
Y نشان دهنده مختصات y یا همون سطرهای پیکسل های پیرامونته که هست n*1
پس باید xc رو که میانگین x هاست از X کم کنی و همچنین yc رو که میانگین y هاست از Y کم کنی یعنی
xc=mean(X)
yc=mean(Y)
XX=X-xc
YY=Y-yc
XX , YY بردارهای مربوط به xها و yهاست که الآن نرمالیزه شده اند و اگه میانگین اونها رو حساب کنی میشه 0و0 (zero mean)
حالا یه ماتریس n*2 ایجاد می کنی به این صورت که ستون اولش x ها و ستون دومش yهاست یعنی
[XX,YY]
و کواریانس اونو حساب می کنی همون طوری که گفتم و بعدش بردارهای ویژه و مقادیر ویژشو تو متلب با eig
که بهت بردار ویژه و مقادیر ویژه رو برمی گردونه
یه راهی به نظرم رسید که ساده تره شاید، اینه که فاصله هر نقطه روی پیرامونو تا تک تک نقاط محاسبه کن که میشه با مرتبه زمانی n2 بعدش اون دونقطه ای که بیشترین فاصله رو دارند میشه همون قطر اصلیت و عمود بر این قطر میشه قطر دیگت. این روش شاید برای همه برگها جواب نده و خطا داشته باشه. باید تست کنی
X نشان دهنده مختصات x یا همون ستونهای پیکسل های پیرامونته که هست n*1
Y نشان دهنده مختصات y یا همون سطرهای پیکسل های پیرامونته که هست n*1
پس باید xc رو که میانگین x هاست از X کم کنی و همچنین yc رو که میانگین y هاست از Y کم کنی یعنی
xc=mean(X)
yc=mean(Y)
XX=X-xc
YY=Y-yc
XX , YY بردارهای مربوط به xها و yهاست که الآن نرمالیزه شده اند و اگه میانگین اونها رو حساب کنی میشه 0و0 (zero mean)
حالا یه ماتریس n*2 ایجاد می کنی به این صورت که ستون اولش x ها و ستون دومش yهاست یعنی
[XX,YY]
و کواریانس اونو حساب می کنی همون طوری که گفتم و بعدش بردارهای ویژه و مقادیر ویژشو تو متلب با eig
که بهت بردار ویژه و مقادیر ویژه رو برمی گردونه
یه راهی به نظرم رسید که ساده تره شاید، اینه که فاصله هر نقطه روی پیرامونو تا تک تک نقاط محاسبه کن که میشه با مرتبه زمانی n2 بعدش اون دونقطه ای که بیشترین فاصله رو دارند میشه همون قطر اصلیت و عمود بر این قطر میشه قطر دیگت. این روش شاید برای همه برگها جواب نده و خطا داشته باشه. باید تست کنی
خیلی ممنون از توجهت مهدی جان
من اون چیزی رو که از حرفات متوجه شدم انجام دادم ولی باز به نتیجه نرسیدم.نمیدونم شاید کار من مشکل داشته. برنامه رو میزارم اگه زحمتی نیست برات یه چک بکن ببین اشکال کار من کجاست.
من یک بار اندازه طول و عرض رو با imtool گرفتم به ترتیب 377 و 305 و یک بارم توسط کدی که نوشتم که جواب هاش کلی با این عددها فرق داشت.
در ضمن اونجایی که گفتی XX , YY بردارهای مربوط به xها و yهاست که الآن نرمالیزه شده اند و اگه میانگین اونها رو حساب کنی میشه 0و0 (zero mean)، من امتحان کردم zero mean نشد.
من کدتو دیدم کاملا درست بود. الآن xx,yy نرمالیزه شدند. من چک کردم میانگین صفر بودند یعنی خیلی نزدیک به صفر بود 12-^10
بعد یه پلات به کد اضافه کردم نتیجه رو ببینی. کدت کاملا صحیح بود من هیچ تغییری ندادم
می تونی با v که جهتو نشون میده و d که یه ضریبی از مقدار طولشونه اون خطها رو رسم کنی. نتیجه خوبه
length_diam1=2*sqrt(d(1,1))*v(:,1); % the length of diameter
length_diam2=2*sqrt(d(2,2))*v(:,2); % the length of diameter
figure;
plot(yy,xx,'.b');
hold on;plot([0,length_diam1(1)],[0,length_diam1(2)],'r');
hold on;plot([0,length_diam2(1)],[0,length_diam2(2)],'r');
من یکم تغییر دادم. لازم نیست پیرامون رو به دست بیاری. با همون تصویر دودویی شده (که پیکسلهای داخلی رو هم شامل میشه) نتیجه بهتره. برای تست می تونی تصویرو بچرخونی و کدو اجرا کنی دوباره
clc
clear all
close all
Image = imread('image.jpg');
if(ndims(Image==3))
Image=rgb2gray(Image);
end
Image=imresize(Image,0.25);
dImage = im2double(Image);
logicalImage = im2bw(dImage, 0.9);
BW=imcomplement(logicalImage);
BW2 = bwareaopen(BW,30);
%BW2 = bwmorph(BW,'remove'); % get the contour
%% Rotation
%BW2=imrotate(BW2,30);
%%
[rr cc]=find(BW2==1);
length_diam1=2*sqrt(d(1,1))*v(:,1); % the length of diameter
length_diam2=2*sqrt(d(2,2))*v(:,2); % the length of diameter
figure;
plot(xx,yy,'.b');
hold on;plot([0,length_diam1(1)],[0,length_diam1(2)],'r');
hold on;plot([0,length_diam2(1)],[0,length_diam2(2)],'r');
دستت درد نکنه مهدی جان خیلی بهتر شده ولی یه مسئله ای که است مطابق اولین شکلی که من برا مثال ذکر کردم نیست منظورم اینکه این فقط قسمتی از این بردارهای متعامد رو رسم میکنه نه کلشو من میخوام این بردارها از هر طرف بروی شکل مماس باشن، مثلا من برنامه رو با 2 تا عکس مختلف کردم که بصورت زیر شد.
خط های زرد رو خودم اضافه کردم که ایدال منه و باید اینطوری رسم بشه. راستی اگه بشه مختصات این 4 نقطه رو که با مشکی مشخص کردم پیدا کنم هم میشه این کارو انجام داد،خواستم ببینم ایده ای تو این زمینه داری؟ View image: 1 View image: 2
دستت درد نکنه مهدی جان خیلی بهتر شده ولی یه مسئله ای که است مطابق اولین شکلی که من برا مثال ذکر کردم نیست منظورم اینکه این فقط قسمتی از این بردارهای متعامد رو رسم میکنه نه کلشو من میخوام این بردارها از هر طرف بروی شکل مماس باشن، مثلا من برنامه رو با 2 تا عکس مختلف کردم که بصورت زیر شد.
خط های زرد رو خودم اضافه کردم که ایدال منه و باید اینطوری رسم بشه. راستی اگه بشه مختصات این 4 نقطه رو که با مشکی مشخص کردم پیدا کنم هم میشه این کارو انجام داد،خواستم ببینم ایده ای تو این زمینه داری؟ View image: 1 View image: 2
کافیه تصویرو به اندازه زاویه به دست اومده بچرخونی تا بلندترین ضلع در سطح افق قرار بگیره، یعنی برگ به صورت افقی قرار گیره و بعد پیکسلهای بر روی هر سطر از تصویرو با هم جمع بزن بنابراین در آخر یک بردار n*1 خواهی داشت یعنی 2,sum(image) و بعدش بیشینه بگیر میان این n عدد. اندیس مورد نظر تعیین کننده مکان آن نقطه ای است که مدنظرت است.(اگر برگت دارای پیکسلهای سفید باشند بیشینه وگرنه کمینه)
این کارو از طرف ستون هم انجام بده. یعنی پیکسلهای هر ستون رو با هم جمع بزن sum(image,1) و بعدش بیشینه بگیر
کافیه تصویرو به اندازه زاویه به دست اومده بچرخونی تا بلندترین ضلع در سطح افق قرار بگیره، یعنی برگ به صورت افقی قرار گیره و بعد پیکسلهای بر روی هر سطر از تصویرو با هم جمع بزن بنابراین در آخر یک بردار n*1 خواهی داشت یعنی 2,sum(image) و بعدش بیشینه بگیر میان این n عدد. اندیس مورد نظر تعیین کننده مکان آن نقطه ای است که مدنظرت است.(اگر برگت دارای پیکسلهای سفید باشند بیشینه وگرنه کمینه)
این کارو از طرف ستون هم انجام بده. یعنی پیکسلهای هر ستون رو با هم جمع بزن sum(image,1) و بعدش بیشینه بگیر
ایده خوبیه جواب هم میده فقط نقطه ضعفش اینکه هرعکس زاویه متفاوتی نسبت به سطح افق داره و در نتیجه برا هرکدوم باید دستی این زاویه رو تنظیم کرد که این کار مثلا برای 2000 تا عکس خیلی وقت میبره،به هرحال بازم ممنون از راهنماییت تا همینجا هم خیلی کمک کردی کلی چیز یاد گرفتم