I counted the grains

Previously posted articles Cell count amnesia

A script that counts the grains made by groping in various ways

I actually implemented it and managed to bring it to a usable level, so I will leave it as a memo.

Purpose

The degree of dirt is judged by counting the number of particles in the liquid. So-called NAS grade Precise measurement is possible with extremely expensive equipment. (↑ Of course I will not make it if I can do this)

However, the rough judgment is a judgment made by the person who looks at the sample. First of all, the purpose is to draw a line to narrow the range of gabagaba and level it.

Creation environment

Windows10 64bit Jupiter Notebook Python 3.6.10 opencv 3.4.2.17 numpy 1.19.0 matplotlib 3.2.2

Library

cap_save.ipynb


import cv2
import sys
import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import time
from datetime import datetime

Basically, image processing using opencv is the main, so use it in this set.

Save image

cap_save.ipynb


#Setting the save destination for captured images
dir_path_class00 = 'Specify save directory/01_class00'
dir_path_class0 = 'Specify save directory/01_class01'
#… Below, set the required amount

#Saved image file name
filename1 = 'original_img'#The original image
filename2 = 'processing_img'#Processed image

#Create save dir(No change)
os.makedirs(dir_path_class00,exist_ok=True)
os.makedirs(dir_path_class0,exist_ok=True)
#… Below, set the required amount

#File path join(The original image:1 and processed image:2 Use the file name when saving)
base_path_00_org = os.path.join(dir_path_class00,filename1)
base_path_00_proc = os.path.join(dir_path_class00,filename2)

base_path_0_org = os.path.join(dir_path_class0,filename1)
base_path_0_proc = os.path.join(dir_path_class0,filename2)
#… Below, set the required amount

#Image save date(* Month * Sun * Hour * Minute)
datename = datetime.now().strftime('%m%d%H%M')

#Name setting when saving an image(When changing, change the relevant part)
name1 = "cell"
name2 = ".jpg "

Strictly speaking, it mainly deals with the old NAS grade, not ISO. For the save destination, we created the save destinations of the old standard grade 00 to grade 12.

I wanted to keep the original image and the processed image (framed), so I set two.

After that, list the scripts required to create the directory and OK.

Read image specification

cap_save.ipynb


#Loading the detected image(The change is at the end ~.jpg only)                   
img = cv2.imread('Specify the save destination and file name of the image you want to check',1)
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

Even if the captured image part was cv2.VideoCapture (), it could be processed without any problem. (It is necessary to change the processing part such as actual binarization.) However, I could not recognize it due to the compatibility problem between the USB camera used for the PC I tried to implement and Opencv. Switched to processing from image selection. (Is it because of the dedicated firmware? I asked the manufacturer, but I haven't answered yet)

If it is a USB camera on the market, it works and can be processed without any problem, so it is okay. Even with a PC camera (● `・ ω ・) ゞ <ok!

Processing part

cap_save.ipynb


#Image size
w, h, = (640, 480)
#magnification
mag = 1

#Process 1
img_blur = cv2.GaussianBlur(img_gray,(5,5),1)
#Kernel set
kernel = np.ones((1,1),dtype=np.uint8)
img_erode = cv2.erode(img_gray,kernel)

def onTrackbar(position):
    global threshold
    threshold = position
cv2.namedWindow("img")
threshold = 100
cv2.createTrackbar("track","img",threshold,255,onTrackbar)

n = 0

while True:
    key = cv2.waitKey(1) & 0xFF
    ret, img_th = cv2.threshold(img_blur,threshold,255,cv2.THRESH_BINARY)
    __,contours, hierarchy = cv2.findContours(img_th.astype(np.uint8),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    img_raw = cv2.resize(img,(w*mag, h*mag))
    img_cut = cv2.drawContours(img_raw, contours, -1,(0,255,255),1)
    #print(len(contours))
    cv2.imshow("img",img_th)
    cv2.imshow("scr",img_cut)
    if key == ord('a'):
        answer = len(contours)
        print("The count number is:",answer,"Pieces")
    
    if key == 27:
        break

As one of the problems, threshold is specified at the time of contour detection, but if it is done with a fixed value, it is inevitable. There was a problem that chitin and contour were not detected depending on the image. Created to change the threshold value with the track bar.

This area was created by referring to the Udemy course.

After that, it was possible to detect to some extent by erode processing due to the relationship between the lens magnification and the number of pixels of the measuring device. I am adding.

I think that this area can be managed by changing it depending on the detected object. After that, the contours when contour detection is set to len (contours) to make it the number of detections.

I had the hardest time here. Speaking of satisfaction, the large outer frame of the image you want to detect has also been counted. To be honest, it's subtle, but I gave up because it's the limit in my mind now.

2020-09-03.png

If you move the track bar like this, you can count from contour detection for the time being.

Judgment from the number of counts

cap_save.ipynb


if answer == 1:
    cv2.imwrite((base_path_00_org + "_" + str(answer) + "cell" + "_" + datename + str(n) + ".jpg "),img)
    cv2.imwrite((base_path_00_proc + "_" + str(answer) + "cell" + "_" + datename + str(n) + ".jpg "),img_cut)
    n += 1
    print("nas grade is:It is equivalent to 00.")

elif answer == 2:
    cv2.imwrite((base_path_0_org + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img)
    cv2.imwrite((base_path_0_proc + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img_cut)
    n += 1
    print("nas grade is:It is equivalent to 0.")

elif 3 <= answer < 5:
    cv2.imwrite((base_path_1_org + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img)
    cv2.imwrite((base_path_1_proc + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img_cut)
    n += 1
    print("nas grade is:It is equivalent to 1.")

… Hereafter, set the required amount.

elif 5780 <= answer:
    cv2.imwrite((base_path_12_org  + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img)
    cv2.imwrite((base_path_12_proc + "_" + str(answer) + name1 + "_" + datename + str(n) + name2),img_cut)
    n += 1
    print("nas grade is:It is equivalent to 12.")
    
cv2.destroyAllWindows()

Refer to the NAS grade class for the threshold value (set value) that is the basis of the judgment. Strictly speaking, it is impossible to make a precise judgment without making a judgment based on the size and number of detected objects. The purpose is to make a simple judgment and draw a line to level out human errors as much as possible. We do not require that level of accuracy.

If you run up to this point, the number of objects whose contours have been detected and the judgment result will be displayed. It is saved in the corresponding directory.

Summary

With this script, it is possible to draw a line with a concrete numerical value. I think we were able to suppress the variation to some extent.

However, the aim is a simple one-shot judgment Accumulate image data to some extent and create learning data based on that data The goal is to make a judgment by reasoning.

After all, it hurts that I couldn't implement GUI. As usual, it was a task that made me cry because I couldn't understand tkinter.

that's all.

Recommended Posts

I counted the grains
I counted bye bye man
I examined the device tree
I touched the Qiita API
I tried the changefinder library!
I downloaded the python source
I read the SHAP paper
I tried the TensorFlow tutorial 1st
I got lost in the maze
I tried the Naro novel API 2
I investigated the mechanism of flask-login!
I participated in the ISUCON10 qualifying!
I tried the TensorFlow tutorial 2nd
I investigated how the scope looks
I liked the tweet with python. ..
I wrote the queue in Python
I tried the Naruro novel API
I tried to move the ball
I tried using the checkio API
I wrote the stack in Python
I tried to estimate the interval.
I don't know the value error
I investigated the device tree Overlay
I checked the gift tax amount
I implemented the K-means method (clustering method)
I tried the TensorFlow tutorial MNIST 3rd
I had google-home perform the beauty conference
I want to pin Spyder to the taskbar
I checked the contents of docker volume
I want to output to the console coolly
I tried the asynchronous server of Django 3.0
I tried to summarize the umask command
I tried tensorflow for the first time
I checked the options of copyMakeBorder of OpenCV
I want to handle the rhyme part1
I summarized the folder structure of Flask
I stumbled on the Hatena Keyword API
I want to handle the rhyme part3
I tried the OSS visualization tool, superset
I didn't know the basics of Python
(Now) I analyzed the new coronavirus (COVID-19)
I tried to summarize the graphical modeling.
I saved the scraped data in CSV!
I wrote the selection sort in C
I can't get the element in Selenium!
I tried to estimate the pi stochastically
[Python] I personally summarized the basic grammar.
I tried to touch the COTOHA API
Python: I tried the traveling salesman problem
The Python project template I think of.
Python's "I can't reach the itch ..." feature
I read the implementation of golang channel
[Python beginner] I collected the articles I wrote
I touched the data preparation tool Paxata
I wrote the sliding wing in creation.
I want to handle the rhyme part2
I want to handle the rhyme part5
I want to handle the rhyme part4
I can't install the package with pip.
I tried the Python Tornado Testing Framework
I tried using the BigQuery Storage API