def make_circle(canvas, seq, bar_rates, tone_name): """色相環一周分の画像を出力""" outer_circle = OuterCircle() for phase in range(0, PHASE_COUNTS): theta = 360/PHASE_COUNTS*phase canvas = make_canvas() bar_box, circle_rail, outer_circle = make_scene1( bar_rates, outer_circle) outer_circle.phase = phase # 円周上の点の位置 circle_rail.theta = theta # バーR bar_box.step1_rect[0].left_top = ( bar_box.red_left, circle_rail.red_p[1]) bar_box.step1_rect[0].right_bottom = ( bar_box.red_left+bar_box.one_width, bar_box.top3) # バーG bar_box.step1_rect[1].left_top = ( bar_box.green_left, circle_rail.green_p[1]) bar_box.step1_rect[1].right_bottom = ( bar_box.green_left+bar_box.one_width, bar_box.top3) # バーB bar_box.step1_rect[2].left_top = ( bar_box.blue_left, circle_rail.blue_p[1]) bar_box.step1_rect[2].right_bottom = ( bar_box.blue_left+bar_box.one_width, bar_box.top3) # print( # f"red={bar_box.step1_rect[0].debug_string} \ # green={bar_box.step1_rect[1].debug_string} \ # blue={bar_box.step1_rect[2].debug_string}") bar_box.delta_3bars_height = calc_step2( bar_box.create_step1_3bars_height(), bar_box.height2 ) # 外環状 theta = outer_circle.phase * outer_circle.unit_arc outer_color = convert_3heights_to_3bytes( bar_box.create_rank23d_3bars_height(), bar_box.height) outer_circle.color_list.append(outer_color) # draw_grid(canvas) # 罫線 bar_box.draw_outline(canvas) # 箱の輪郭 canvas = draw_canvas(canvas, bar_box, circle_rail, outer_circle) draw_tone_name(canvas, bar_box, tone_name) # トーン名 # 書出し canvas = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB) # BGRをRGBにする cv2.imwrite(f"./@share/out-cstep4-{seq}.png", canvas) seq += 1 return seq, canvas
def update_scene1_with_rotate(vertical_parcent, phase, bar_box, circle_rail, outer_circle, inscribed_triangle): """回転が伴うモデルを更新""" theta = 360 / PHASE_COUNTS * phase outer_circle.phase = phase # 円周上の点の位置 circle_rail.theta = theta # print( # f"vertical_parcent=({vertical_parcent[0]}, {vertical_parcent[1]}, \ # {vertical_parcent[2]}) theta={theta}") color_rate = to_color_rate(vertical_parcent, theta) # print( # f"color_rate=({color_rate[0]}, {color_rate[1]}, {color_rate[2]})") # バーの高さに変換 red_bar_height = int(color_rate[0] * bar_box.height) green_bar_height = int(color_rate[1] * bar_box.height) blue_bar_height = int(color_rate[2] * bar_box.height) # print( # f"red_bar_height={red_bar_height} green_bar_height={green_bar_height} \ # blue_bar_height={blue_bar_height}") # バーR ( (left, top), (right, bottom) ) # バーG # バーB bar_box.n3bars_rect = (Rectangle(bar_box.red_left, bar_box.bottom - red_bar_height, bar_box.red_left + bar_box.one_width, bar_box.top3), Rectangle(bar_box.green_left, bar_box.bottom - green_bar_height, bar_box.green_left + bar_box.one_width, bar_box.top3), Rectangle(bar_box.blue_left, bar_box.bottom - blue_bar_height, bar_box.blue_left + bar_box.one_width, bar_box.top3)) # 外環状 theta = outer_circle.phase * outer_circle.unit_arc rank23d_3bars_height = bar_box.create_rank23d_3bars_height() outer_circle.color_list.append( convert_3heights_to_3bytes(rank23d_3bars_height, bar_box.height)) # inscribed_triangle.update(bar_box.top2, bar_box.top3, circle_rail.center, theta, rank23d_3bars_height) gravity = inscribed_triangle.triangular_center_of_gravity() diff_xy = (gravity[0] - circle_rail.center[0], gravity[1] - circle_rail.center[1]) inscribed_triangle.correct_horizon(diff_xy)
def update_scene1_with_rotate(phase, bar_box, circle_rail, outer_circle, inscribed_triangle): """回転が伴うモデルを更新""" theta = 360 / PHASE_COUNTS * phase outer_circle.phase = phase # 円周上の点の位置 circle_rail.theta = theta # バーR bar_box.step1_rect[0].left_top = (bar_box.red_left, circle_rail.red_p[1]) bar_box.step1_rect[0].right_bottom = (bar_box.red_left + bar_box.one_width, bar_box.top3) # バーG bar_box.step1_rect[1].left_top = (bar_box.green_left, circle_rail.green_p[1]) bar_box.step1_rect[1].right_bottom = (bar_box.green_left + bar_box.one_width, bar_box.top3) # バーB bar_box.step1_rect[2].left_top = (bar_box.blue_left, circle_rail.blue_p[1]) bar_box.step1_rect[2].right_bottom = (bar_box.blue_left + bar_box.one_width, bar_box.top3) # print( # f"red={bar_box.step1_rect[0].debug_string} \ # green={bar_box.step1_rect[1].debug_string} \ # blue={bar_box.step1_rect[2].debug_string}") bar_box.delta_3bars_height = calc_step2( bar_box.create_step1_3bars_height(), bar_box.height2) # 外環状 theta = outer_circle.phase * outer_circle.unit_arc rank23d_3bars_height = bar_box.create_rank23d_3bars_height() outer_color = convert_3heights_to_3bytes(rank23d_3bars_height, bar_box.height) outer_circle.color_list.append(outer_color) # inscribed_triangle.update(bar_box.top2, bar_box.top3, circle_rail.center, theta, rank23d_3bars_height) gravity = inscribed_triangle.triangular_center_of_gravity() diff_xy = (gravity[0] - circle_rail.center[0], gravity[1] - circle_rail.center[1]) inscribed_triangle.correct_horizon(diff_xy)
def draw_canvas(canvas, bar_box, circle_rail, outer_circle, inscribed_triangle): """アニメの1コマを作成します""" circle_rail.draw_circle(canvas) # 円レール circle_rail.draw_triangle(canvas) # 円に内接する正三角形 circle_rail.draw_border(canvas) # 背景の上限、下限の線 inscribed_triangle.draw(canvas) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) rank23d_3bars_height = bar_box.create_rank23d_3bars_height() rank23d_color = convert_3heights_to_3bytes(rank23d_3bars_height, bar_box.height) bar_box.draw_3bars(canvas) # RGBバー bar_box.draw_y_axis_label(canvas) # バー率テキスト # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ cv2.line(canvas, inscribed_triangle.rbg_points[0], (bar_box.red_left, bar_box.red_top), RED, thickness=2) # 水平線G cv2.line( canvas, inscribed_triangle.rbg_points[2], # 青と緑が入れ替わっているのが工夫 (bar_box.green_left, bar_box.green_top), GREEN, thickness=2) # 水平線B cv2.line(canvas, inscribed_triangle.rbg_points[1], (bar_box.blue_left, bar_box.blue_top), BLUE, thickness=2) outer_circle.draw_me(canvas) # 外環状 # 時計の針 tickness = 2 inner_range = circle_rail.range1 second_range = int(6.5 * GRID_UNIT) - tickness third_range = int(7.5 * GRID_UNIT) + tickness inner_p = ( int(inner_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(inner_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = ( int(second_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(second_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, PALE_GRAY, thickness=2) # 時計の針の先 # 楕円、描画する画像を指定、座標(x,y),xyの半径、角度,色、線の太さ(-1は塗りつぶし) start_angle = int(circle_rail.theta - outer_circle.unit_arc / 2) end_angle = int(circle_rail.theta + outer_circle.unit_arc / 2) if start_angle == end_angle: end_angle += 1 # 差が 0 だと変なとこ描画するんで cv2.ellipse(canvas, circle_rail.center, (second_range, second_range), -90, start_angle, end_angle, PALE_GRAY, thickness=tickness) cv2.ellipse(canvas, circle_rail.center, (third_range, third_range), -90, start_angle, end_angle, PALE_GRAY, thickness=tickness) # # バー箱の2段目の黒枠 bar_box.draw_rank2_box(canvas) # 色成分数 bar_box.draw_rgb_number(canvas, rank23d_color) # gravity = inscribed_triangle.triangular_center_of_gravity() # debug # cv2.putText(canvas, # f"theta={circle_rail.theta}", # # f"theta={circle_rail.theta} phase={outer_circle.phase} \ # gravity=({gravity[0]:5.1f}, {gravity[1]:5.1f})", # (10, 10), # x,y # cv2.FONT_HERSHEY_SIMPLEX, # FONT_SCALE, # BLACK, # lineType=2) # f"multiple=({n3bars_multiple[0]:7.3f}, {n3bars_multiple[1]:7.3f}, {n3bars_multiple[2]:7.3f})", # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas
def draw_canvas(canvas, bar_box, circle_rail, inner_circle, outer_circle): """アニメの1コマを作成します""" circle_rail.draw_me(canvas) # 円レール circle_rail.draw_red_p(canvas) # 円周上の点R circle_rail.draw_green_p(canvas) # 円周上の点G circle_rail.draw_blue_p(canvas) # 円周上の点B # 円に内接する線。三角形 cv2.line(canvas, circle_rail.red_p, circle_rail.green_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.green_p, circle_rail.blue_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.blue_p, circle_rail.red_p, BLACK, thickness=2) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) a_color = convert_3heights_to_3bytes(bar_box.addition_3bars_height, bar_box.height) step1_color = convert_3heights_to_3bytes( bar_box.create_step1_3bars_height(), bar_box.height) rank3_color = convert_3heights_to_3bytes( bar_box.create_rank3_3bars_height(), bar_box.height) rank23_color = convert_3heights_to_3bytes( bar_box.create_rank23_3bars_height(), bar_box.height) rank23a_color = convert_3heights_to_3bytes( bar_box.create_rank23a_3bars_height(), bar_box.height) # 3色成分(配色) a_3colors = (DARK_RED, DARK_GREEN, DARK_BLUE) step1_3colors = (VIVID_RED, VIVID_GREEN, VIVID_BLUE) rank3_3colors = (BRIGHT_RED, BRIGHT_GREEN, BRIGHT_BLUE) rank23a_3colors = (RED, GREEN, BLUE) # # (WIP) 成分から角度を逆算 # element_rates, expected_theta = calc_color_element_rates(rank23_color) # if circle_rail.theta != expected_theta: # print( # f"theta={circle_rail.theta:>7.3f}~{expected_theta:>7.3f} \ # color_element(rank23_color)=({element_rates[0]:>7.3f}, \ # {element_rates[1]:>7.3f}, \ # {element_rates[2]:>7.3f})") bar_box.draw_3bars(canvas, a_3colors, step1_3colors, rank3_3colors) # RGBバー # 色見本 筆算の線 line_left = bar_box.left - 14 * GRID_INTERVAL_H line_right = bar_box.right + 4 * GRID_INTERVAL_H line_top = bar_box.bottom + int(13 * GRID_INTERVAL_H) cv2.line(canvas, (line_left, line_top), (line_right, line_top), LIGHT_GRAY, thickness=2) # プラス記号 color_example_width = 3 * GRID_INTERVAL_H font = cv2.FONT_HERSHEY_SIMPLEX font_scale = FONT_SCALE line_type = 2 cv2.putText( canvas, "+", (int(bar_box.left - 4.5 * color_example_width), int(bar_box.bottom + 11.5 * GRID_INTERVAL_H)), # x,y font, font_scale, BLACK, line_type) color_example_left = int(bar_box.left - 1.5 * color_example_width) # 括線 cv2.ellipse(canvas, (bar_box.left - GRID_INTERVAL_H, bar_box.bottom + int(8.5 * GRID_INTERVAL_H)), (3 * GRID_INTERVAL_H, 3 * GRID_INTERVAL_H), 90, 0, 180, PALE_GRAY, thickness=2) # 色見本 rank23 left_top = (int(color_example_left - 3.5 * GRID_INTERVAL_H), int(bar_box.bottom + int(7.5 * GRID_INTERVAL_H))) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23_color, thickness=-1) # 色見本 # 色見本 23a left_top = (color_example_left, int(bar_box.bottom + int(14.5 * GRID_INTERVAL_H))) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23a_color, thickness=-1) # 色見本 bar_box.draw_bar_rate_rank13(canvas) # バー率テキスト bar_box.draw_bar_rate_rank2(canvas) # バー率テキスト # 色成分数 bar_box.draw_rgb_number(canvas, a_color, a_3colors, step1_color, step1_3colors, rank3_color, rank3_3colors, rank23a_color, rank23a_3colors) # 時計の針 clock_hand_len = 8 * GRID_INTERVAL_H inner_p = (int(circle_rail.range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(circle_rail.range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = (int((circle_rail.range + clock_hand_len) * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int((circle_rail.range + clock_hand_len) * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, LIGHT_GRAY, thickness=2) # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ cv2.line(canvas, circle_rail.red_p, (bar_box.step1_rect[0].right_bottom[0], circle_rail.red_p[1]), step1_3colors[0], thickness=2) # 水平線G cv2.line(canvas, circle_rail.green_p, (bar_box.step1_rect[1].right_bottom[0], circle_rail.green_p[1]), step1_3colors[1], thickness=2) # 水平線B cv2.line(canvas, circle_rail.blue_p, (bar_box.step1_rect[2].right_bottom[0], circle_rail.blue_p[1]), step1_3colors[2], thickness=2) inner_circle.draw_me(canvas) # 内環状 outer_circle.draw_me(canvas) # 外環状 # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas
def draw_canvas(canvas, bar_box, circle_rail, outer_circle): """アニメの1コマを作成します""" circle_rail.draw_me(canvas) # 円レール circle_rail.draw_red_p(canvas) # 円周上の点R circle_rail.draw_green_p(canvas) # 円周上の点G circle_rail.draw_blue_p(canvas) # 円周上の点B # 背景の上限、下限の線 cv2.line(canvas, (circle_rail.center[0] - 2*circle_rail.range, int(circle_rail.center[1] - circle_rail.range)), (circle_rail.center[0] + 2*circle_rail.range, int(circle_rail.center[1] - circle_rail.range)), PALE_GRAY, thickness=2) cv2.line(canvas, (circle_rail.center[0] - 2*circle_rail.range, int(circle_rail.center[1] + circle_rail.range)), (circle_rail.center[0] + 2*circle_rail.range, int(circle_rail.center[1] + circle_rail.range)), PALE_GRAY, thickness=2) # 円に内接する線。正三角形 cv2.line(canvas, circle_rail.red_p, circle_rail.green_p, WHITE, thickness=2) cv2.line(canvas, circle_rail.green_p, circle_rail.blue_p, WHITE, thickness=2) cv2.line(canvas, circle_rail.blue_p, circle_rail.red_p, WHITE, thickness=2) # 調整された三角形 # bar_box.create_rank23d_3bars_height() n3bars_multiple = bar_box.create_3bars_multiple() circle_rail.calc_fitted_p(n3bars_multiple) cv2.line(canvas, circle_rail.fitted_red_p, circle_rail.fitted_green_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.fitted_green_p, circle_rail.fitted_blue_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.fitted_blue_p, circle_rail.fitted_red_p, BLACK, thickness=2) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) rank23d_color = convert_3heights_to_3bytes( bar_box.create_rank23d_3bars_height(), bar_box.height) # # (WIP) 成分から角度を逆算 # element_rates, expected_theta = calc_color_element_rates(rank23_color) # if circle_rail.theta != expected_theta: # print( # f"theta={circle_rail.theta:>7.3f}~{expected_theta:>7.3f} \ # color_element(rank23_color)=({element_rates[0]:>7.3f}, \ # {element_rates[1]:>7.3f}, \ # {element_rates[2]:>7.3f})") bar_box.draw_3bars(canvas) # RGBバー bar_box.draw_y_axis_label(canvas) # バー率テキスト # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ top = bar_box.step1_rect[0].left_top[1] - bar_box.delta_3bars_height[0] cv2.line(canvas, circle_rail.fitted_red_p, (bar_box.step1_rect[0].left_top[0], top), RED, thickness=2) # 水平線G top = bar_box.step1_rect[1].left_top[1] - bar_box.delta_3bars_height[1] cv2.line(canvas, circle_rail.fitted_green_p, (bar_box.step1_rect[1].left_top[0], top), GREEN, thickness=2) # 水平線B top = bar_box.step1_rect[2].left_top[1] - bar_box.delta_3bars_height[2] cv2.line(canvas, circle_rail.fitted_blue_p, (bar_box.step1_rect[2].left_top[0], top), BLUE, thickness=2) outer_circle.draw_me(canvas) # 外環状 # 時計の針 tickness = 2 inner_range = circle_rail.range second_range = int(6.5*GRID_UNIT)-tickness third_range = int(7.5*GRID_UNIT)+tickness inner_p = ( int(inner_range * math.cos(math.radians(circle_rail.theta-90)) + circle_rail.center[0]), int(inner_range * math.sin(math.radians(circle_rail.theta-90))+circle_rail.center[1])) outer_p = ( int(second_range * math.cos(math.radians(circle_rail.theta-90))+circle_rail.center[0]), int(second_range * math.sin(math.radians(circle_rail.theta-90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, PALE_GRAY, thickness=2) # 時計の針の先 # 楕円、描画する画像を指定、座標(x,y),xyの半径、角度,色、線の太さ(-1は塗りつぶし) cv2.ellipse(canvas, circle_rail.center, (second_range, second_range), -90, int(circle_rail.theta-outer_circle.unit_arc/2), int(circle_rail.theta+outer_circle.unit_arc/2), PALE_GRAY, thickness=tickness) cv2.ellipse(canvas, circle_rail.center, (third_range, third_range), -90, int(circle_rail.theta-outer_circle.unit_arc/2), int(circle_rail.theta+outer_circle.unit_arc/2), PALE_GRAY, thickness=tickness) # # バー箱の2段目の黒枠 bar_box.draw_rank2_box(canvas) # 色成分数 bar_box.draw_rgb_number(canvas, rank23d_color) # debug # cv2.putText(canvas, f"multiple=({n3bars_multiple[0]:7.3f}, {n3bars_multiple[1]:7.3f}, {n3bars_multiple[2]:7.3f})", # f"zoom={circle_rail.zoom}", # # f"delta_color=({delta_color[0]}, {delta_color[1]}, {delta_color[2]})", # f"delta_3bars_height=({bar_box.delta_3bars_height[0]}, \ # {bar_box.delta_3bars_height[1]}, \ # {bar_box.delta_3bars_height[2]})", # (10, 10), # x,y # cv2.FONT_HERSHEY_SIMPLEX, # FONT_SCALE, # BLACK, # lineType=2) # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas
def draw_canvas(canvas, bar_box, circle_rail, outer_circle): """アニメの1コマを作成します""" circle_rail.draw_circle(canvas) # 円レール circle_rail.draw_triangle(canvas) # 円に内接する線。正三角形 circle_rail.draw_red_p(canvas) # 円周上の点R circle_rail.draw_green_p(canvas) # 円周上の点G circle_rail.draw_blue_p(canvas) # 円周上の点B # 背景の上限、下限の線 cv2.line(canvas, (circle_rail.center[0] - 2 * circle_rail.range, int(circle_rail.center[1] - circle_rail.range)), (circle_rail.center[0] + 2 * circle_rail.range, int(circle_rail.center[1] - circle_rail.range)), PALE_GRAY, thickness=2) cv2.line(canvas, (circle_rail.center[0] - 2 * circle_rail.range, int(circle_rail.center[1] + circle_rail.range)), (circle_rail.center[0] + 2 * circle_rail.range, int(circle_rail.center[1] + circle_rail.range)), PALE_GRAY, thickness=2) # 調整された三角形 # 赤、緑、青 の点の位置関係は全部で12相です rank23d_3bars_height = bar_box.create_rank23d_3bars_height() red = rank23d_3bars_height[0] green = rank23d_3bars_height[1] blue = rank23d_3bars_height[2] triangle_theta = circle_rail.theta # +phase*30 if green == blue and blue < red: # 緑と青は等しく、それより赤が上 phase = 0 elif blue < green and green < red: # 下から青、緑、赤 phase = 1 elif blue < green and green == red: # 青より大きい緑は赤と等しい phase = 2 elif blue < red and red < green: # 下から青、赤、緑 phase = 3 triangle_theta -= 120 elif blue == red and red < green: # 青と赤は等しく、それより緑が上 phase = 4 triangle_theta -= 120 elif red < blue and blue < green: # 下から赤、青、緑 phase = 5 triangle_theta -= 120 elif red < blue and blue == green: # 赤より大きい青は緑と等しい phase = 6 triangle_theta -= 120 elif red < green and green < blue: # 下から赤、緑、青 phase = 7 triangle_theta += 120 elif red == green and green < blue: # 赤と緑は等しく、それより青が上 phase = 8 triangle_theta += 120 elif green < red and red < blue: # 下から緑、赤、青 phase = 9 triangle_theta += 120 elif green < red and red == blue: # 緑より大きい赤は青と等しい phase = 10 else: # 下から緑、青、赤 phase = 11 # 赤、青、緑 の順なのが工夫 rbg_points = calc_triangle(bar_box.top2, bar_box.top3, triangle_theta, circle_rail.center) if phase == 0: # 緑や青より赤が上 pass elif phase == 1: # 下から青、緑、赤 pass elif phase == 2: # 青より、緑と赤が上 pass elif phase == 3: # 下から青、赤、緑 rbg_points = (rbg_points[2], rbg_points[1], rbg_points[0]) elif phase == 4: # 青や赤より緑が上 rbg_points = (rbg_points[1], rbg_points[2], rbg_points[0]) elif phase == 5: # 下から赤、青、緑 rbg_points = (rbg_points[1], rbg_points[2], rbg_points[0]) elif phase == 6: # 赤より、青と緑が上 rbg_points = (rbg_points[1], rbg_points[2], rbg_points[0]) elif phase == 7: # 下から赤、緑、青 rbg_points = (rbg_points[1], rbg_points[0], rbg_points[2]) elif phase == 8: # 赤や緑より青が上 rbg_points = (rbg_points[2], rbg_points[0], rbg_points[1]) elif phase == 9: # 下から緑、赤、青 rbg_points = (rbg_points[2], rbg_points[0], rbg_points[1]) elif phase == 10: # 緑より、赤と青が上 rbg_points = (rbg_points[0], rbg_points[2], rbg_points[1]) else: # 下から緑、青、赤 rbg_points = (rbg_points[0], rbg_points[2], rbg_points[1]) cv2.line(canvas, rbg_points[0], rbg_points[1], BLACK, thickness=2) cv2.line(canvas, rbg_points[1], rbg_points[2], BLACK, thickness=2) cv2.line(canvas, rbg_points[2], rbg_points[0], BLACK, thickness=2) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) rank23d_color = convert_3heights_to_3bytes(rank23d_3bars_height, bar_box.height) # # (WIP) 成分から角度を逆算 # element_rates, expected_theta = calc_color_element_rates(rank23_color) # if circle_rail.theta != expected_theta: # print( # f"theta={circle_rail.theta:>7.3f}~{expected_theta:>7.3f} \ # color_element(rank23_color)=({element_rates[0]:>7.3f}, \ # {element_rates[1]:>7.3f}, \ # {element_rates[2]:>7.3f})") bar_box.draw_3bars(canvas) # RGBバー bar_box.draw_y_axis_label(canvas) # バー率テキスト # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ top = bar_box.step1_rect[0].left_top[1] - bar_box.delta_3bars_height[0] cv2.line(canvas, rbg_points[0], (bar_box.step1_rect[0].left_top[0], top), RED, thickness=2) # 水平線G top = bar_box.step1_rect[1].left_top[1] - bar_box.delta_3bars_height[1] cv2.line( canvas, rbg_points[2], # 青と緑が入れ替わっているのが工夫 (bar_box.step1_rect[1].left_top[0], top), GREEN, thickness=2) # 水平線B top = bar_box.step1_rect[2].left_top[1] - bar_box.delta_3bars_height[2] cv2.line(canvas, rbg_points[1], (bar_box.step1_rect[2].left_top[0], top), BLUE, thickness=2) outer_circle.draw_me(canvas) # 外環状 # 時計の針 tickness = 2 inner_range = circle_rail.range second_range = int(6.5 * GRID_UNIT) - tickness third_range = int(7.5 * GRID_UNIT) + tickness inner_p = ( int(inner_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(inner_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = ( int(second_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(second_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, PALE_GRAY, thickness=2) # 時計の針の先 # 楕円、描画する画像を指定、座標(x,y),xyの半径、角度,色、線の太さ(-1は塗りつぶし) cv2.ellipse(canvas, circle_rail.center, (second_range, second_range), -90, int(circle_rail.theta - outer_circle.unit_arc / 2), int(circle_rail.theta + outer_circle.unit_arc / 2), PALE_GRAY, thickness=tickness) cv2.ellipse(canvas, circle_rail.center, (third_range, third_range), -90, int(circle_rail.theta - outer_circle.unit_arc / 2), int(circle_rail.theta + outer_circle.unit_arc / 2), PALE_GRAY, thickness=tickness) # # バー箱の2段目の黒枠 bar_box.draw_rank2_box(canvas) # 色成分数 bar_box.draw_rgb_number(canvas, rank23d_color) # debug cv2.putText( canvas, f"triangle_theta={triangle_theta} phase={phase}", (10, 10), # x,y cv2.FONT_HERSHEY_SIMPLEX, FONT_SCALE, BLACK, lineType=2) # f"multiple=({n3bars_multiple[0]:7.3f}, {n3bars_multiple[1]:7.3f}, {n3bars_multiple[2]:7.3f})", # f"zoom={circle_rail.zoom}", # # f"delta_color=({delta_color[0]}, {delta_color[1]}, {delta_color[2]})", # f"delta_3bars_height=({bar_box.delta_3bars_height[0]}, \ # {bar_box.delta_3bars_height[1]}, \ # {bar_box.delta_3bars_height[2]})", # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas
def draw_canvas(canvas, bar_box, circle_rail, inner_circle, outer_circle): """アニメの1コマを作成します""" circle_rail.draw_me(canvas) # 円レール circle_rail.draw_red_p(canvas) # 円周上の点R circle_rail.draw_green_p(canvas) # 円周上の点G circle_rail.draw_blue_p(canvas) # 円周上の点B # 円に内接する線。三角形 cv2.line(canvas, circle_rail.red_p, circle_rail.green_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.green_p, circle_rail.blue_p, BLACK, thickness=2) cv2.line(canvas, circle_rail.blue_p, circle_rail.red_p, BLACK, thickness=2) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) a_color = convert_3heights_to_3bytes(bar_box.addition_3bars_height, bar_box.height) step1_color = convert_3heights_to_3bytes( bar_box.create_step1_3bars_height(), bar_box.height) rank3_byte = convert_height_to_byte(bar_box.height3, bar_box.height) rank23_color = convert_3heights_to_3bytes( bar_box.create_rank23_3bars_height(), bar_box.height) rank23a_color = convert_3heights_to_3bytes( bar_box.create_rank23a_3bars_height(), bar_box.height) # 3色成分(配色) a_3colors = (DARK_RED, DARK_GREEN, DARK_BLUE) step1_3colors = (VIVID_RED, VIVID_GREEN, VIVID_BLUE) rank3_3colors = (BRIGHT_RED, BRIGHT_GREEN, BRIGHT_BLUE) rank23a_3colors = (RED, GREEN, BLUE) # # (WIP) 成分から角度を逆算 # element_rates, expected_theta = calc_color_element_rates(rank23_color) # if circle_rail.theta != expected_theta: # print( # f"theta={circle_rail.theta:>7.3f}~{expected_theta:>7.3f} \ # color_element(rank23_color)=({element_rates[0]:>7.3f}, \ # {element_rates[1]:>7.3f}, \ # {element_rates[2]:>7.3f})") bar_box.draw_3bars(canvas, a_3colors, step1_3colors, rank3_3colors) # RGBバー # プラス記号 color_example_width = int(1.5 * GRID_UNIT) color_example_left = int(bar_box.left - 1.5 * color_example_width) # 色見本 23a left_top = (color_example_left, int(bar_box.bottom + int(2.5 * GRID_UNIT))) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23a_color, thickness=-1) # 色見本 # 色見本 rank23 left_top = (color_example_left, int(bar_box.bottom + 3.75 * GRID_UNIT)) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23_color, thickness=-1) # 色見本 bar_box.draw_y_axis_label(canvas) # バー率テキスト # 時計の針 clock_hand_len = int(4.5 * GRID_UNIT) inner_p = (int(circle_rail.range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(circle_rail.range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = (int((circle_rail.range + clock_hand_len) * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int((circle_rail.range + clock_hand_len) * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, LIGHT_GRAY, thickness=2) # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ cv2.line(canvas, circle_rail.red_p, (bar_box.step1_rect[0].right_bottom[0], circle_rail.red_p[1]), step1_3colors[0], thickness=2) # 水平線G cv2.line(canvas, circle_rail.green_p, (bar_box.step1_rect[1].right_bottom[0], circle_rail.green_p[1]), step1_3colors[1], thickness=2) # 水平線B cv2.line(canvas, circle_rail.blue_p, (bar_box.step1_rect[2].right_bottom[0], circle_rail.blue_p[1]), step1_3colors[2], thickness=2) inner_circle.draw_me(canvas) # 内環状 outer_circle.draw_me(canvas) # 外環状 # バー箱の2段目の黒枠 bar_box.draw_rank2_box(canvas) # 色成分数 bar_box.draw_rgb_number(canvas, a_color, a_3colors, step1_color, step1_3colors, rank3_byte, rank23_color, rank23a_color, rank23a_3colors) # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas
def draw_canvas(canvas, bar_box, circle_rail, inner_circle, outer_circle): """アニメの1コマを作成します""" circle_rail.draw_me(canvas) # 円レール circle_rail.draw_red_p(canvas) # 円周上の点R circle_rail.draw_green_p(canvas) # 円周上の点G circle_rail.draw_blue_p(canvas) # 円周上の点B # 円に内接する線。三角形 cv2.line(canvas, circle_rail.red_p, circle_rail.green_p, WHITE, thickness=2) cv2.line(canvas, circle_rail.green_p, circle_rail.blue_p, WHITE, thickness=2) cv2.line(canvas, circle_rail.blue_p, circle_rail.red_p, WHITE, thickness=2) # 1色成分 (高さから 255 へ丸めるとき、誤差が出る) delta_color = convert_3heights_to_3bytes(bar_box.delta_3bars_height, bar_box.height) step1_color = convert_3heights_to_3bytes( bar_box.create_step1_3bars_height(), bar_box.height) rank3_byte = convert_height_to_byte(bar_box.height3, bar_box.height) rank23_color = convert_3heights_to_3bytes( bar_box.create_rank23_3bars_height(), bar_box.height) rank23d_color = convert_3heights_to_3bytes( bar_box.create_rank23a_3bars_height(), bar_box.height) # 3色成分(配色) delta_3colors = (DARK_RED, DARK_GREEN, DARK_BLUE) step1_3colors = (VIVID_RED, VIVID_GREEN, VIVID_BLUE) rank3_3colors = (BRIGHT_RED, BRIGHT_GREEN, BRIGHT_BLUE) # # (WIP) 成分から角度を逆算 # element_rates, expected_theta = calc_color_element_rates(rank23_color) # if circle_rail.theta != expected_theta: # print( # f"theta={circle_rail.theta:>7.3f}~{expected_theta:>7.3f} \ # color_element(rank23_color)=({element_rates[0]:>7.3f}, \ # {element_rates[1]:>7.3f}, \ # {element_rates[2]:>7.3f})") bar_box.draw_3bars(canvas, delta_3colors, step1_3colors, rank3_3colors) # RGBバー bar_box.draw_y_axis_label(canvas) # バー率テキスト color_example_width = int(1.5 * GRID_UNIT) left = bar_box.left - 2 * color_example_width swing_bar_width = int(0.75 * color_example_width) right = left + swing_bar_width color_example_left = int(left - color_example_width) # 最大値 upper_bound_y = circle_rail.upper_bound_y() # 最小値 lower_bound_y = circle_rail.lower_bound_y() # 色見本 23a left_top = (bar_box.left - color_example_width, bar_box.top2 - color_example_width) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23d_color, thickness=-1) # 色見本 # 正三角形の振動を表示 # inner cv2.rectangle(canvas, (left, upper_bound_y), (right, lower_bound_y), WHITE, thickness=-1) cv2.rectangle(canvas, (left, lower_bound_y), (right, bar_box.bottom), BRIGHT_GRAY, thickness=-1) # diameter left = bar_box.left - color_example_width cv2.rectangle(canvas, (left, bar_box.top2), (left + swing_bar_width, bar_box.top3), BLACK, thickness=-1) cv2.rectangle(canvas, (left, bar_box.top3), (left + swing_bar_width, bar_box.bottom), BRIGHT_GRAY, thickness=-1) # 色見本 rank23 left_top = (color_example_left + color_example_width, int(upper_bound_y - color_example_width)) right_bottom = (left_top[0] + color_example_width, left_top[1] + color_example_width) cv2.rectangle(canvas, left_top, right_bottom, rank23_color, thickness=-1) # 色見本 # 水平線R # 線、描画する画像を指定、座標1点目、2点目、色、線の太さ if delta_color[0] > -1: line_color = step1_3colors[0] else: line_color = delta_3colors[0] cv2.line(canvas, circle_rail.red_p, (bar_box.step1_rect[0].right_bottom[0], circle_rail.red_p[1]), line_color, thickness=2) # 水平線G if delta_color[1] > -1: line_color = step1_3colors[1] else: line_color = delta_3colors[1] cv2.line(canvas, circle_rail.green_p, (bar_box.step1_rect[1].right_bottom[0], circle_rail.green_p[1]), line_color, thickness=2) # 水平線B if delta_color[2] > -1: line_color = step1_3colors[2] else: line_color = delta_3colors[2] cv2.line(canvas, circle_rail.blue_p, (bar_box.step1_rect[2].right_bottom[0], circle_rail.blue_p[1]), line_color, thickness=2) inner_circle.draw_me(canvas) # 内環状 outer_circle.draw_me(canvas) # 外環状 # 時計の針 inner_range = circle_rail.range second_range = int(5.5 * GRID_UNIT) third_range = int(6.5 * GRID_UNIT) fourth_range = int(7.5 * GRID_UNIT) inner_p = ( int(inner_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(inner_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = ( int(second_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(second_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, PALE_GRAY, thickness=2) # inner_p = ( int(second_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(second_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = ( int((third_range) * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int((third_range) * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, WHITE, thickness=2) # inner_p = ( int(third_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(third_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) outer_p = ( int(fourth_range * math.cos(math.radians(circle_rail.theta - 90)) + circle_rail.center[0]), int(fourth_range * math.sin(math.radians(circle_rail.theta - 90)) + circle_rail.center[1])) cv2.line(canvas, inner_p, outer_p, BLACK, thickness=2) # # バー箱の2段目の黒枠 bar_box.draw_rank2_box(canvas) # 色成分数 bar_box.draw_rgb_number(canvas, delta_color, step1_color, rank3_byte, rank23d_color) # debug # cv2.putText(canvas, # # f"delta_color=({delta_color[0]}, {delta_color[1]}, {delta_color[2]})", # f"delta_3bars_height=({bar_box.delta_3bars_height[0]}, \ # {bar_box.delta_3bars_height[1]}, \ # {bar_box.delta_3bars_height[2]})", # (10, 10), # x,y # cv2.FONT_HERSHEY_SIMPLEX, # FONT_SCALE, # BLACK, # lineType=2) # cv2.imshow('Title', canvas) # cv2.imwrite('form.jpg',canvas) # cv2.waitKey(0) # cv2.destroyAllWindows() return canvas