Answers.Body: <p>To better distinguish the <code>vinculum vs. minus</code>, you have a few options.</p>
  <ol>
  <li><p>First, you may add more examples of each in your training set.</p>
  </li>
  <li><p>Alternatively, you may develop a second classifier (<code>vinculum vs. minus</code> subclassifier) that operates in tandem with your first
  &quot;general purpose&quot; classifier (<code>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +, -, /]</code>) which you already have.  The subclassifier is triggered only
  when the first classifier predicts <strong>either a vinculum or minus</strong>.
  Since your subclassifier is expected to be more accurate than than
  the first classifier for the subtask of distinguishing between
  vinculum and minus, you use the prediction of the former as the
  final verdict.  In summary, the first classifier is a selector for
  <code>either vinculum or minus</code>, and the second (sub)classifier is a
  discriminator for <code>which vinculum or minus</code>.</p>
  </li>
  </ol>
  <p>Note:  For the <code>vinculum vs. minus</code> subtask, you may perform some old fashioned image analysis.  First, derive a mathematic representation of the bar.  Next, extract the <code>length</code> of the bar and the <code>angle</code> the bar makes with respect to the horizontal.  Finally, these two tabular features can be used in one of the many options of machine learning algorithms at your disposal.  For this subtask, it is possible that this approach may yield better results than deep learning.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-11-06T09:49:44.363Z
Answers.LastActivityDate: 2022-11-06T10:49:33.963Z
Answers.LastEditDate: 2022-11-06T10:49:33.963Z
Answers.UserDisplayName: Snehal Patel
Body: <p>I am working in a project named &quot;Handwritten Math Evaluation&quot;. So what basically happens in this is that there are 11 classes of (0 - 9) and (+, -) each containing 50 clean handwritten digits in them. Then I trained a CNN model for it with 80 % of data used in training and 20 % using in testing of model which results in an accuracy of 98.83 %. Here is the code for the architecture of CNN model:</p>
  <pre><code>import pandas as pd 
  import numpy as np 
  import pickle 
  np.random.seed(1212) 
  import keras 
  from keras.models import Model 
  from keras.layers import *
  from keras import optimizers 
  from keras.layers import Input, Dense 
  from keras.models import Sequential 
  from keras.layers import Dense 
  from keras.layers import Dropout 
  from keras.layers import Flatten 
  from keras.layers.convolutional import Conv2D 
  from keras.layers.convolutional import MaxPooling2D 
  from keras.utils import np_utils 
  from keras import backend as K  
  from keras.utils.np_utils import to_categorical 
  from keras.models import model_from_json
  import matplotlib.pyplot as plt
  model = Sequential() 
  model.add(Conv2D(30, (5, 5), input_shape =(28,28,1), activation ='relu')) 
  model.add(MaxPooling2D(pool_size =(2, 2))) 
  model.add(Conv2D(15, (3, 3), activation ='relu')) 
  model.add(MaxPooling2D(pool_size =(2, 2))) 
  model.add(Dropout(0.2)) 
  model.add(Flatten()) 
  model.add(Dense(128, activation ='relu')) 
  model.add(Dense(50, activation ='relu')) 
  model.add(Dense(12, activation ='softmax')) 
  # Compile model 
  model.compile(loss ='categorical_crossentropy', 
              optimizer ='adam', metrics =['accuracy']) 
  model.fit(X_train, y_train, epochs=1000)
  </code></pre>
  <p>Now each image in dataset is preprocessed as follows:</p>
  <pre><code>import cv2
  im = cv2.imread(path)
  im_gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
  ret, im_th = cv2.threshold(im_gray, 90, 255, cv2.THRESH_BINARY_INV)
  ctrs, hier = cv2.findContours(im_th.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  rects = [cv2.boundingRect(ctr) for ctr in ctrs]
  rect = rects[0]
  im_crop =im_th[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
  im_resize = cv2.resize(im_crop,(28,28))
  im_resize = np.array(im_resize)
  im_resize=im_resize.reshape(28,28)
  </code></pre>
  <p>I have made an evaluation function which solves simple expression like 7+8 :-</p>
  <pre><code>def evaluate(im):
      s = ''
      data = []
      im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
      ret, im_th = cv2.threshold(im_gray, 90, 255, cv2.THRESH_BINARY_INV)
      ctrs, hier = cv2.findContours(im_th.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0])
      boundingBoxes = [cv2.boundingRect(c) for c in ctrs]
      look_up = ['0','1','2','3','4','5','6','7','8','9','+','-'] 
      i=0
      for c in ctrs:
          rect = boundingBoxes[i]
          im_crop = im_th[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
          im_resize = cv2.resize(im_crop,(28,28))
          im_resize = np.array(im_resize)
          im_resize = im_resize.reshape(28,28,1)
          data.append(im_resize)
          i+=1
      data = np.array(data)
      predictions = model.predict(data)
      i=0
      while i&lt;len(boundingBoxes):
          rect = boundingBoxes[i]
          print(rect[2],rect[3])
          print(predictions[i])
          s += look_up[predictions[i].argmax()]
          i+=1
      return s
  </code></pre>
  <p>I need help extending this to compound fractions, but the problem is that the vinculum <code>/</code> is identical to the subtraction sign <code>-</code> when resized to (28, 28). So I need help in distinguishing between them.</p>
  <p>This is my first question, so please let me know if any details are left.</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-11-17T03:31:57.320Z
Comments.Text: Welcome to SE:AI!  We focus on the conceptual aspects, as opposed to programming questions.  Can I ask is there a way to ask the core conceptual question without so much of the code?
Comments.UserDisplayName: DukeZhou
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-11-17T05:10:12.270Z
Comments.Text: I though to give all the details
Comments.UserDisplayName: Dhaval Bothra
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-11-17T05:27:54.557Z
Comments.Text: We appreciate earnestness—I was concerned that the question has received two close votes and no answers as yet.  (My thought was emphasizing the conceptual could facilitate getting the information that could help you solve your specific problem.  Right now, I have to wonder if including all of the imports and ancillary code is keeping people away.)
Comments.UserDisplayName: DukeZhou
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-11-17T07:48:51.700Z
Comments.Text: Ok I will edit the question
Comments.UserDisplayName: Dhaval Bothra
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-10-25T02:01:35.003Z
Comments.Text: It seems like the question was in fact edited but the problem @DukeZhou indicated of "all of the imports and ancillary code" has not been addressed.  I suggest heavily editing the post to conform to SE:AI guidelines (see https://ai.stackexchange.com/help/on-topic and https://ai.stackexchange.com/help/how-to-ask).
Comments.UserDisplayName: Snehal Patel
Tags: <computer-vision><tensorflow><python><keras><opencv>
Title: Distinguishing between handwritten compound fraction and subtraction
UserDisplayName: Dhaval Bothra
ThreadText: # Distinguishing between handwritten compound fraction and subtraction
  
  (Asked by: username_0 on 2020-10-30)
  
  I am working in a project named "Handwritten Math Evaluation". So what basically happens in this is that there are 11 classes of (0 - 9) and (+, -) each containing 50 clean handwritten digits in them. Then I trained a CNN model for it with 80 % of data used in training and 20 % using in testing of model which results in an accuracy of 98.83 %. Here is the code for the architecture of CNN model:
  import pandas as pd 
  import numpy as np 
  import pickle 
  np.random.seed(1212) 
  import keras 
  from keras.models import Model 
  from keras.layers import *
  from keras import optimizers 
  from keras.layers import Input, Dense 
  from keras.models import Sequential 
  from keras.layers import Dense 
  from keras.layers import Dropout 
  from keras.layers import Flatten 
  from keras.layers.convolutional import Conv2D 
  from keras.layers.convolutional import MaxPooling2D 
  from keras.utils import np_utils 
  from keras import backend as K  
  from keras.utils.np_utils import to_categorical 
  from keras.models import model_from_json
  import matplotlib.pyplot as plt
  model = Sequential() 
  model.add(Conv2D(30, (5, 5), input_shape =(28,28,1), activation ='relu')) 
  model.add(MaxPooling2D(pool_size =(2, 2))) 
  model.add(Conv2D(15, (3, 3), activation ='relu')) 
  model.add(MaxPooling2D(pool_size =(2, 2))) 
  model.add(Dropout(0.2)) 
  model.add(Flatten()) 
  model.add(Dense(128, activation ='relu')) 
  model.add(Dense(50, activation ='relu')) 
  model.add(Dense(12, activation ='softmax')) 
  # Compile model 
  model.compile(loss ='categorical_crossentropy', 
              optimizer ='adam', metrics =['accuracy']) 
  model.fit(X_train, y_train, epochs=1000)
  
  Now each image in dataset is preprocessed as follows:
  import cv2
  im = cv2.imread(path)
  im_gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
  ret, im_th = cv2.threshold(im_gray, 90, 255, cv2.THRESH_BINARY_INV)
  ctrs, hier = cv2.findContours(im_th.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  rects = [cv2.boundingRect(ctr) for ctr in ctrs]
  rect = rects[0]
  im_crop =im_th[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
  im_resize = cv2.resize(im_crop,(28,28))
  im_resize = np.array(im_resize)
  im_resize=im_resize.reshape(28,28)
  
  I have made an evaluation function which solves simple expression like 7+8 :-
  def evaluate(im):
      s = ''
      data = []
      im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
      ret, im_th = cv2.threshold(im_gray, 90, 255, cv2.THRESH_BINARY_INV)
      ctrs, hier = cv2.findContours(im_th.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0])
      boundingBoxes = [cv2.boundingRect(c) for c in ctrs]
      look_up = ['0','1','2','3','4','5','6','7','8','9','+','-'] 
      i=0
      for c in ctrs:
          rect = boundingBoxes[i]
          im_crop = im_th[rect[1]:rect[1]+rect[3], rect[0]:rect[0]+rect[2]]
          im_resize = cv2.resize(im_crop,(28,28))
          im_resize = np.array(im_resize)
          im_resize = im_resize.reshape(28,28,1)
          data.append(im_resize)
          i+=1
      data = np.array(data)
      predictions = model.predict(data)
      i=0
      while i
  I need help extending this to compound fractions, but the problem is that the vinculum / is identical to the subtraction sign - when resized to (28, 28). So I need help in distinguishing between them.
  This is my first question, so please let me know if any details are left.
  
  **Tags:** computer-vision, tensorflow, python, keras, opencv
  > **Comments:**
  > **username_1**: Welcome to SE:AI!  We focus on the conceptual aspects, as opposed to programming questions.  Can I ask is there a way to ask the core conceptual question without so much of the code?  
  > **username_0**: I though to give all the details  
  > **username_1**: We appreciate earnestness—I was concerned that the question has received two close votes and no answers as yet.  (My thought was emphasizing the conceptual could facilitate getting the information that could help you solve your specific problem.  Right now, I have to wonder if including all of the imports and ancillary code is keeping people away.)  
  > **username_0**: Ok I will edit the question  
  > **username_2**: It seems like the question was in fact edited but the problem @DukeZhou indicated of "all of the imports and ancillary code" has not been addressed.  I suggest heavily editing the post to conform to SE:AI guidelines (see https://ai.stackexchange.com/help/on-topic and https://ai.stackexchange.com/help/how-to-ask).  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2022-11-06. Score: 0
  
  To better distinguish the `vinculum vs. minus`, you have a few options.
  
  1. First, you may add more examples of each in your training set.
  2. Alternatively, you may develop a second classifier (`vinculum vs. minus` subclassifier) that operates in tandem with your first
     "general purpose" classifier (`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +, -, /]`) which you already have. The subclassifier is triggered only
     when the first classifier predicts **either a vinculum or minus**.
     Since your subclassifier is expected to be more accurate than than
     the first classifier for the subtask of distinguishing between
     vinculum and minus, you use the prediction of the former as the
     final verdict. In summary, the first classifier is a selector for
     `either vinculum or minus`, and the second (sub)classifier is a
     discriminator for `which vinculum or minus`.
  
  Note: For the `vinculum vs. minus` subtask, you may perform some old fashioned image analysis. First, derive a mathematic representation of the bar. Next, extract the `length` of the bar and the `angle` the bar makes with respect to the horizontal. Finally, these two tabular features can be used in one of the many options of machine learning algorithms at your disposal. For this subtask, it is possible that this approach may yield better results than deep learning.
  
  
  ---
  
  