MINISTRY OF EDUCATION AND TRAINING HO CHI MINH CITY UNIVERSITY OF TECHNOLOGY AND EDUCATION FACULTY OF ELECTRICAL AND ELECTRONICS ENGINEERING GRADUATION THESIS MAJOR: BIOMEDICAL ENGINEERING DESIGN OF A GEL CARD READER FOR BLOOD GROUPING TESTS ADVISOR: Assoc Prof Dr NGUYEN THANH HAI STUDENT’S NAME: TRUONG HOANG GIA BAO STUDENT ID: 16129007 STUDENT’S NAME: NGUYEN MINH DUC STUDENT ID: 16129017 SKL 0 HO CHI MINH CITY, JANUARY 2021 an HO CHI MINH CITY UNIVERSITY OF TECHNOLOGY AND EDUCATION FACULTY OF ELECTRICAL AND ELECTRONICS ENGINEERING DEPARTMENT OF ELECTRONICS - BIOMEDICAL ENGINEERING - GRADUATION THESIS MAJOR: BIOMEDICAL ENGINEERING PROJECT NAME: DESIGN OF A GEL CARD READER FOR BLOOD GROUPING TESTS Advisor: Assoc Prof Dr NGUYEN THANH HAI Truong Hoang Gia Bao Student ID: 16129007 Nguyen Minh Duc Student ID: 16129017 an HO CHI MINH CITY UNIVERSITY OF TECHNOLOGY AND EDUCATION FACULTY OF ELECTRICAL AND ELECTRONICS ENGINEERING DEPARTMENT OF ELECTRONICS - BIOMEDICAL ENGINEERING - GRADUATION THESIS MAJOR: BIOMEDICAL ENGINEERING PROJECT NAME: DESIGN OF A GEL CARD READER FOR BLOOD GROUPING TESTS Advisor: Assoc Prof Dr NGUYEN THANH HAI Truong Hoang Gia Bao Student ID: 16129007 Nguyen Minh Duc Student ID: 16129017 Ho Chi Minh City, January 2021 an HCMC UNIVERSITY OF TECHNOLOGY AND EDUCATION Faculty of Electrical & Electronics Engineering Department of Electronics Industrial-Biomedical Engineering THE SOCIALIST REPUBLIC OF VIETNAM Independence – Freedom– Happiness Ho Chi Minh City, January 20, 2021 MISSION Student name: Major: Type of training: Year: Trương Hoàng Gia Bảo Nguyễn Minh Đức Biomedical Engineering Regular full time 2016 Student ID: 16129007 Student ID: 16129017 Major ID: D520212 Code: Class: 161290 I GRADUATION PROJECT: II MISSION Initial resources: ● Raspberry Pi 4B ● Webcam Hoco D101 ● Gel Card Implementation: ● Use a Python programming language ● Design PCB and make a power supply board ● Design and make a 3D model ● Design the entire model of the project ● Self-evaluate the entire project III DATE OF DELIVERY: IV DATE OF COMPLETION: V ADVISOR NAME: ADVISOR 07/10/2020 20/01/2021 Assoc Prof Dr NGUYEN THANH HAI DEPARTMENT OF ELECTRONICS INDUSTRIALBIOMEDICAL ENGINEERING v an HCMC UNIVERSITY OF TECHNOLOGY AND EDUCATION THE SOCIALIST REPUBLIC OF VIETNAM Faculty of Electrical & Electronics Engineering Independence – Freedom– Happiness Department of Electronics Industrial-Biomedical Engineering o0o Ho Chi Minh City, October 28, 2020 SCHEDULE Student name: Trương Hoàng Gia Bảo Student ID: 16129007 Student name: Nguyễn Minh Đức Student ID: 16129017 Class: 161290 Graduation project: Design of a Gel Card reader for blood grouping test Week Week 1st (October 12 October 18) Task description Lecturer confirm - Meet the advisor to listen to the request for doing a project, choose a project topic Week 2nd (October 19 October 25) Week 3rd (October 26 – November ) Week 4th & week 5th (November November 15) Week 6th & week 7th (November 16 – November 29) Week 8th & week 9th (November 30 December 13) Week 10th & week 11th (December 14 December 27) - Advisor reviews topic - Write an abstract of the selected topic: what the topic purpose is, the design request, the limits of the topic - Research into a theoretical basis of the project on many resources - Buy components, make the power supply board - Design the prototype and conduct experiments - Design software, hardware for the product and conducting experiments - Check the product's accuracy with actual samples and recalibrate - Write the thesis report vi an Week 12th & week 13th (December 28 – January 10) Week 14th & week 15th (January 11 January 24) - Continue conducting experiments - Complete the model and the thesis report - Submit the final version of the thesis report and report the thesis - Submit to the advisor for the last inspection Week 16th (January 25 – January 31) - Make a presentation ADVISOR (Sign and write your full name) vii an GUARANTEE We guarantee that this project is our research, under Assoc Prof Dr NGUYEN THANH HAI 's guidance The results published in this project are honest and are not replicated from any other work Students: Nguyễn Minh Đức Trương Hoàng Gia Bảo viii an ACKNOWLEDGMENTS In order to complete this graduation project, the first words of our group would like to say sincere thanks to Assoc Prof Dr NGUYEN THANH HAI for his dedication that helps us a lot in order to accomplish our project In the process of doing this thesis, Dr Hai not only provides us useful knowledge but also trains us to have a serious attitude in scientific research, which is very necessary for the career path later The group would like to thank the teachers in the Department of Industrial Electronics - Biomedical Engineering for providing the best conditions for us to complete the topic Besides, we would like to thank all the lecturers who taught us foundation knowledge in the previous semesters for the group was able to complete the project Thank you to Ms Huong, Head of Laboratory Department - Thu Duc General Hospital, to provide Gel Card samples for us to complete this project Thank you to Nghia Tin Medical Equipment Co., Ltd, to support the group with the equipment and ideas to implement the topic Thank Mr Ngo Thien Ha - Deputy Director of Duong Phu Technology Co., Ltd has provided the group facilities and equipment to implement the project Thank parents, for your hard-working in raising us to school The more extended the period spending on working, the more we understand the suffering of our parents Finally, we would like to express our sincere thanks to the people who have contributed and helped the group to implement this project successfully Sincerely thanks! Ho Chi Minh City, January 20, 2021 Students Nguyễn Minh Đức Trương Hoàng Gia Bảo ix an TABLE OF CONTENTS Cover i Mission ii Schedule iii Guarante ix Acknowledgments ixi Table of contents ixii List of figures x List of tables xii Abstract xiiii Chapter INTRODUCTION 1.1 PROBLEM STATEMENT .1 1.2 OBJECTIVE .2 1.3 THESIS CONTENTS .2 1.4 LIMITATIONS 1.5 BRIEF SUMMARY OF THESIS .2 Chapter LITERATURE REVIEW 2.1 TYPES OF HUMAN BLOOD 2.2 GEL CARD METHOD AND TYPE OF GEL CARDS 2.2.1 Gel Card method .5 2.2.2 Type of Gel Cards 2.3 IMAGE PROCESSING ALGORITHM 2.3.1 Dilation method 2.3.2 Edge detection method 2.4 IMAGE CAPTURING DEVICES 2.4.1 Microprocessor introduction 2.4.2 Description of power supply 12 Chapter DESIGN AND CALCULATION 13 3.1 INTRODUCTION 13 3.2 CALCULATION AND DESIGN 13 3.2.1 Block Diagram Of An Capturing Device .13 3.2.2 Image Capturing Device .14 x an 3.2.3 Central Processing Unit 14 3.2.4 Image Display and Peripherals .15 3.2.5 Calculation of Power Supply 15 3.2.6 Case designs for the Gel Card Reader 25 3.3 DEVICE CONNECTION .27 3.4 FLOWCHART AND PROGRAM ALGORITHM 28 3.4.1 Functional summary of Gel Card Reader .28 3.4.2 Flowchart 28 3.4.3 A flowchart of agglutination level and blood type .29 3.5 PRINCIPLE OF OPERATION 36 Chapter CONNECTION OF SYSYTEM PARTS 37 4.1 INTRODUCTION 37 4.2 POWER SUPPLY 37 4.2.1 Assembly of the Power Supply 37 4.2.2 Execution of The Power Supply 37 4.2.3 Inspection of The Power Supply 40 4.3 EXECUTION THE CASE OF GEL CARD READER 41 4.4 SYSTEM CONSTRUCTION 41 4.4.1 User Interfere Design 41 4.4.2 Model Construction 42 4.5 PROGRAMMING SOFTWARE 42 4.5.1 Python Programming Software 42 4.5.2 Image processing program 43 4.5.3 QT Designer 44 Chapter RESULTS AND DISCUSSION 46 5.1 GENERAL RESULTS 46 5.2 ACHIEVEMENT RESULTS 46 5.2.1 Power Supply 46 5.2.2 GUI .49 5.2.3 System modelling result .50 5.2.4 Test results 50 5.2.5 Result of Gel Card Reader 51 5.2.6 Actual Results .54 5.3 INSTRUCTION 55 viii an APPENDIX def displayImage(self, window=1): qformat = QImage.Format_Indexed8 if len(self.image.shape) == 3: if (self.image.shape[2]) == 4: qformat = QImage.Format_RGBA8888 else: qformat = QImage.Format_RGB888 img = QImage(self.image, self.image.shape[1], self.image.shape[0], qformat) img = img.rgbSwapped() self.label_9.setPixmap(QPixmap.fromImage(img)) # serPixmap setPixmap self.label_9.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) def open_img(self): fname, filter = QFileDialog.getOpenFileName(self, 'Open File', 'C:\\Users\DELL\PycharmProjects\DemoPro', "Image Files (*)") if fname: self.loadImage(fname) else: print("Invalid Image") # cap = cv2.VideoCapture(0) # ret, frame = cap.read() # self.displayImage(frame, 1) # self.displayImage(frame, 1) # cap.release() # cv2.destroyAllWindows() def save_img(self): fname, filter = QFileDialog.getSaveFileName(self, 'Save File', 'C:\\', "Image Files (*.png)") if fname: cv2.imwrite(fname, self.image) # Lưu trữ ảnh print("Error") def AboutMessage(self): QMessageBox.about(self, "About Qt - Qt Designer", "Qt is a multiplatform C + + GUI toolkit created and maintained byTrolltech.It provides application developers with all the functionality needed to build applications with state-of-the-art graphical user interfaces.\n" "Qt is fully object-oriented, easily extensible, and allows true component programming.Read the Whitepaper for a comprehensive technical overview.\n\n" "Since its commercial introduction in early 1996, Qt has formed the basis of many thousands of successful applications worldwide.Qt is also the basis of the popular KDE Linux desktop environment, a standard component of all major Linux distributions.See our Customer Success Stories for some examples of commercial Qt development.\n\n" "Qt is supported on the following platforms:\n\n" "\tMS / Windows - - 95, 98, NT\n" DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX "\t4.0, ME, 2000, and XP\n" "\tUnix / X11 - - Linux, Sun\n" "\tSolaris, HP - UX, Compaq Tru64 UNIX, IBM AIX, SGI IRIX and a wide range of others\n" "\tMacintosh - - Mac OS X\n" "\tEmbedded - - Linux platforms with framebuffer support.\n\n" "Qt is released in different editions:\n\n" "\tThe Qt Enterprise Edition and the Qt Professional Edition provide for commercial software development.They permit traditional commercial software distribution and include free upgrades and Technical Support.For the latest prices, see the Trolltech web site, Pricing and Availability page, or contact sales @ trolltech.com.The Enterprise Edition offers additional modules compared to the Professional Edition.\n\n" "\tThe Qt Open Source Edition is available for Unix / X11, Macintosh and Embedded Linux.The Open Source Edition is for the development of Free and Open Source software only.It is provided free of charge under the terms of both the Q Public License and the GNU General Public License." ) def AboutMessage2(self): QMessageBox.about(self, "About Author", "Lecturer: Assoc Prof Dr Nguyen Thanh Hai \n\n" "Student:\n" "\tNguyen Minh Duc - ID: 16129017 " "\t Truong Hoang Gia Bao - ID: 16129007" ) def QuestionMessage(self): message = QMessageBox.question(self, "Exit", "Bạn có muốn thoát", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) if message == QMessageBox.Yes: print("Yes") self.close() else: print("No") def ReadGelcard(self): roi1 = self.image[274:274 + 255, 423:423 + 75] roi2 = self.image[274:274 + 255, 564:564 + 75] roi3 = self.image[274:274 + 255, 708:708 + 75] roi4 = self.image[274:274 + 255, 855:855 + 75] roi5 = self.image[274:274 + 255, 1002:1002 + 75] roi6 = self.image[274:274 + 255, 1145:1145 + 75] roi7 = self.image[274:274 + 255, 1289:1289 + 75] roi8 = self.image[274:274 + 255, 1427:1427 + 75] roi1 = cv2.resize(roi1, None, fx=0.5, fy=0.5) hsv1 = cv2.cvtColor(roi1, cv2.COLOR_BGR2HSV) roi2 = cv2.resize(roi2, None, fx=0.5, fy=0.5) hsv2 = cv2.cvtColor(roi2, cv2.COLOR_BGR2HSV) roi3 = cv2.resize(roi3, None, fx=0.5, fy=0.5) hsv3 = cv2.cvtColor(roi3, cv2.COLOR_BGR2HSV) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX roi4 = cv2.resize(roi4, None, fx=0.5, fy=0.5) hsv4 = cv2.cvtColor(roi4, cv2.COLOR_BGR2HSV) roi5 = cv2.resize(roi5, None, fx=0.5, fy=0.5) hsv5 = cv2.cvtColor(roi5, cv2.COLOR_BGR2HSV) roi6 = cv2.resize(roi6, None, fx=0.5, fy=0.5) hsv6 = cv2.cvtColor(roi6, cv2.COLOR_BGR2HSV) roi7 = cv2.resize(roi7, None, fx=0.5, fy=0.5) hsv7 = cv2.cvtColor(roi7, cv2.COLOR_BGR2HSV) roi8 = cv2.resize(roi8, None, fx=0.5, fy=0.5) hsv8 = cv2.cvtColor(roi8, cv2.COLOR_BGR2HSV) # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv1, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv1, lower_red, upper_red) mask = mask1 + mask2 output1 = cv2.bitwise_and(hsv1, roi1, mask=mask) gray1 = cv2.cvtColor(output1, cv2.COLOR_RGB2GRAY) ret, threshold1 = cv2.threshold(gray1, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation1 = cv2.dilate(threshold1, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX cv2.circle(roi1, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq1 = self.textBrowser_3.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi1, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq1 = self.textBrowser_3.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi1, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq1 = self.textBrowser_3.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi1, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq1 = self.textBrowser_3.setText('Positive (1+)') else: cv2.circle(roi1, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq1 = self.textBrowser_3.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv2, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv2, lower_red, upper_red) mask = mask1 + mask2 output = cv2.bitwise_and(hsv2, roi2, mask=mask) gray2 = cv2.cvtColor(output, cv2.COLOR_RGB2GRAY) ret, threshold2 = cv2.threshold(gray2, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation2 = cv2.dilate(threshold2, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi2, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq2 = self.textBrowser_4.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi2, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq2 = self.textBrowser_4.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi2, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq2 = self.textBrowser_4.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi2, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq2 = self.textBrowser_4.setText('Positive (1+)') else: cv2.circle(roi2, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq2 = self.textBrowser_4.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv3, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv3, lower_red, upper_red) mask = mask1 + mask2 output3 = cv2.bitwise_and(hsv3, roi3, mask=mask) gray3 = cv2.cvtColor(output3, cv2.COLOR_RGB2GRAY) ret, threshold3 = cv2.threshold(gray3, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX dilation3 = cv2.dilate(threshold3, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation3, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi3, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq3 = self.textBrowser_5.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi3, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq3 = self.textBrowser_5.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi3, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq3 = self.textBrowser_5.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi3, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq3 = self.textBrowser_5.setText('Positive (1+)') else: cv2.circle(roi3, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq3 = self.textBrowser_5.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX mask1 = cv2.inRange(hsv4, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv4, lower_red, upper_red) mask = mask1 + mask2 output4 = cv2.bitwise_and(hsv4, roi4, mask=mask) gray4 = cv2.cvtColor(output4, cv2.COLOR_RGB2GRAY) ret, threshold4 = cv2.threshold(gray4, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation4 = cv2.dilate(threshold4, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation4, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi4, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq4 = self.textBrowser_9.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi4, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq4 = self.textBrowser_9.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi4, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq4 = self.textBrowser_9.setText('Positive (2+)') DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX elif indexY > 80 and indexY < 95: cv2.circle(roi4, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq4 = self.textBrowser_9.setText('Positive (1+)') else: cv2.circle(roi4, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq4 = self.textBrowser_9.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv5, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv5, lower_red, upper_red) mask = mask1 + mask2 output5 = cv2.bitwise_and(hsv5, roi5, mask=mask) gray5 = cv2.cvtColor(output5, cv2.COLOR_RGB2GRAY) ret, threshold5 = cv2.threshold(gray5, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation5 = cv2.dilate(threshold5, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation5, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi5, (indexX, indexY), 3, (255, 255, 255), -1) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX stringState.append('Duong tinh (4+)') kq5 = self.textBrowser_10.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi5, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq5 = self.textBrowser_10.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi5, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq5 = self.textBrowser_10.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi5, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq5 = self.textBrowser_10.setText('Positive (1+)') else: cv2.circle(roi5, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq5 = self.textBrowser_10.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv6, lower_red, upper_red) lower_red = np.array([170, 70, 50]) upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv6, lower_red, upper_red) mask = mask1 + mask2 output6 = cv2.bitwise_and(hsv6, roi6, mask=mask) gray6 = cv2.cvtColor(output6, cv2.COLOR_RGB2GRAY) ret, threshold6 = cv2.threshold(gray6, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation6 = cv2.dilate(threshold6, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation6, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi6, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq6 = self.textBrowser_8.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi6, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq6 = self.textBrowser_8.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi6, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq6 = self.textBrowser_8.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi6, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq6 = self.textBrowser_8.setText('Positive (1+)') else: cv2.circle(roi6, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq6 = self.textBrowser_8.setText('Negative (-)') # mask microtube lower_red = np.array([0, 26, 141]) upper_red = np.array([179, 255, 255]) mask1 = cv2.inRange(hsv7, lower_red, upper_red) lower_red = np.array([0, 26, 141]) upper_red = np.array([179, 255, 255]) mask = mask1 + mask2 output7 = cv2.bitwise_and(hsv7, roi7, mask=mask) gray7 = cv2.cvtColor(output7, cv2.COLOR_RGB2GRAY) ret, threshold7 = cv2.threshold(gray7, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation7 = cv2.dilate(threshold7, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation7, cv2.RETR_TREE, DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi7, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq7 = self.textBrowser_6.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi7, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq7 = self.textBrowser_6.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi7, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq7 = self.textBrowser_6.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi7, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') kq7 = self.textBrowser_6.setText('Positive (1+)') else: cv2.circle(roi7, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq7 = self.textBrowser_6.setText('Negative (-)') # mask microtube lower_red = np.array([0, 70, 50]) upper_red = np.array([10, 255, 255]) mask1 = cv2.inRange(hsv8, lower_red, upper_red) lower_red = np.array([170, 70, 50]) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX upper_red = np.array([180, 255, 255]) mask2 = cv2.inRange(hsv8, lower_red, upper_red) mask = mask1 + mask2 output8 = cv2.bitwise_and(hsv8, roi8, mask=mask) gray8 = cv2.cvtColor(output8, cv2.COLOR_RGB2GRAY) ret, threshold8 = cv2.threshold(gray8, 10, 255, 0) kernel = np.ones((5, 5), np.uint8) dilation8 = cv2.dilate(threshold8, kernel, iterations=1) contours, hierarchy = cv2.findContours(dilation8, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) total_contours = len(contours) print('Phat hien: ', total_contours) locations = [] for contour in contours: M = cv2.moments(contour) cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) print('Tam theo truc x:', cX, ' Tam theo truc y', cY) locations.append([cX, cY]) def takeFirst(elem): return elem[0] locations.sort(key=takeFirst) stringState = [] for location in locations: indexY = location[1] indexX = location[0] if indexY < 60: cv2.circle(roi8, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (4+)') kq8 = self.textBrowser_7.setText('Positive (4+)') elif indexY > 60 and indexY < 70: cv2.circle(roi8, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (3+)') kq8 = self.textBrowser_7.setText('Positive (3+)') elif indexY > 70 and indexY < 80: cv2.circle(roi8, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (2+)') kq8 = self.textBrowser_7.setText('Positive (2+)') elif indexY > 80 and indexY < 95: cv2.circle(roi8, (indexX, indexY), 3, (255, 255, 255), -1) stringState.append('Duong tinh (1+)') DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX kq8 = self.textBrowser_7.setText('Positive (1+)') else: cv2.circle(roi8, (indexX, indexY), 3, (0, 0, 0), -1) stringState.append('Am tinh (-)') kq8 = self.textBrowser_7.setText('Negative (-)') if kq4 == and kq8 == 0: if (kq1 > 1) and (kq2 > 1) and kq3 > 1: print("Sample 1, Blood group: (AB+)") self.textBrowser.setText('Sample 1, Blood group: (AB+)') elif (kq1 > 0) and (kq2 > 0) and kq3 == 0: print("Sample 1, Blood group: (AB-)") self.textBrowser.setText('Sample 1, Blood group: (AB-)') elif kq1 == and kq2 > and kq3 > 0: print("Sample 1, Blood group: (B+)") self.textBrowser.setText('Sample 1, Blood group: (B+)') elif kq1 == and kq2 > and kq3 == 0: print("Sample 1, Blood group: (B-)") self.textBrowser.setText('Sample 1, Blood group: (B-)') elif kq1 > and kq2 == and kq3 > 0: print("Sample 1, Blood group: (A+)") self.textBrowser.setText('Sample 1, Blood group: (A+)') elif kq1 > and kq2 == and kq3 == 0: print("Sample 1, Blood group: (A-)") self.textBrowser.setText('Sample 1, Blood group: (A-)') elif kq1 == and kq2 == and kq3 > 0: print("Sample 1, Blood group: (O+)"); self.textBrowser.setText('Sample 1, Blood group: (O+)') elif kq1 == and kq2 == and kq3 == 0: print("Sample 1, Blood group: (O-)"); self.textBrowser.setText('Sample 1, Blood group: (O-)') if (kq5 > 1) and (kq6 > 1) and kq7 > 1: print("Sample 2, Blood group: (AB+)") self.textBrowser_2.setText('Sample 2, Blood group: (AB+)') elif (kq5 > 0) and (kq6 > 0) and kq7 == 0: print("Sample 2, Blood group: (AB-)") self.textBrowser_2.setText('Sample 2, Blood group: (AB-)') elif kq5 == and kq6 > and kq7 > 0: print("Sample 2, Blood group: (B+)") self.textBrowser_2.setText('Sample 2, Blood group: (B+)') elif kq5 == and kq6 > and kq7 == 0: print("Sample 2, Blood group: (B-)") self.textBrowser_2.setText('Sample 2, Blood group: (B-)') elif kq5 > and kq6 == and kq7 > 0: print("Sample 2, Blood group: (A+)") self.textBrowser_2.setText('Sample 2, Blood group: (A+)') elif kq5 > and kq6 == and kq7 == 0: print("Sample 2, Blood group: (A-)") self.textBrowser_2.setText('Sample 2, Blood group: (A-)') elif kq5 == and kq6 == and kq7 > 0: print("Sample 2, Blood group: (O+)"); self.textBrowser_2.setText('Sample 2, Blood group: (O+)') elif kq5 == and kq6 == and kq7 == 0: print("Sample 2, Blood group: (O-)"); self.textBrowser_2.setText('Sample 2, Blood group: (O-)') DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an APPENDIX else: self.textBrowser.setText('Wrong Gelcard, please use another Gelcard') self.textBrowser_2.setText('Wrong Gelcard, please use another Gelcard') print("Wrong Gelcard, please use another Gelcard") ########################################Moire Pattern########################################################## import hinhanh app = QApplication(sys.argv) win = LoadQt() win.show() sys.exit(app.exec()) DEPARTMENT OF ELECTRONIC – BIOMEDICAL ENGINEERING an S an K L 0 ... "Design of a Gel Card Reader for blood grouping tests. " will have the function of reading Gel Card in the blood group test, identifying faulty Card and managing patient information Here use a. .. field of medical tests For the above reasons, the group decided to implement the graduation thesis ? ?Design of a Gel Card Reader for blood grouping tests. ” The Gel Card Reader uses a camera to take... negative 2.2.2 Type of Gel Cards a) Forward grouping Gel Card Forward grouping Gel Card has micro tubes, each test uses tubes A, B, D and Ctrl Tube A contains antibodies A, tube B contains antibodies